Explicitly encode keyof behaviors for never and unknown into getIndexType (#30753)

* Explicitly encode keyof behaviors for never and unknown into getIndexType

* Merge similar cases
This commit is contained in:
Wesley Wigham
2019-04-15 17:52:13 -07:00
committed by GitHub
parent 3dc78b6f3b
commit d405662eb6
11 changed files with 1723 additions and 1307 deletions
@@ -0,0 +1,42 @@
interface TextChannel {
id: string;
type: 'text';
phoneNumber: string;
}
interface EmailChannel {
id: string;
type: 'email';
addres: string;
}
type Channel = TextChannel | EmailChannel;
export type ChannelType = Channel extends { type: infer R } ? R : never;
type Omit<T, K extends keyof T> = Pick<
T,
({ [P in keyof T]: P } & { [P in K]: never } & { [x: string]: never })[keyof T]
>;
type ChannelOfType<T extends ChannelType, A = Channel> = A extends { type: T }
? A
: never;
export type NewChannel<T extends Channel> = Pick<T, 'type'> &
Partial<Omit<T, 'type' | 'id'>> & { localChannelId: string };
export function makeNewChannel<T extends ChannelType>(type: T): NewChannel<ChannelOfType<T>> {
const localChannelId = `blahblahblah`;
return { type, localChannelId };
}
const newTextChannel = makeNewChannel('text');
// This should work
newTextChannel.phoneNumber = '613-555-1234';
const newTextChannel2 : NewChannel<TextChannel> = makeNewChannel('text');
// Compare with this, which ofc works.
newTextChannel2.phoneNumber = '613-555-1234';
@@ -33,7 +33,8 @@ type K03 = keyof boolean; // "valueOf"
type K04 = keyof void; // never
type K05 = keyof undefined; // never
type K06 = keyof null; // never
type K07 = keyof never; // never
type K07 = keyof never; // string | number | symbol
type K08 = keyof unknown; // never
type K10 = keyof Shape; // "name" | "width" | "height" | "visible"
type K11 = keyof Shape[]; // "length" | "toString" | ...