-
Notifications
You must be signed in to change notification settings - Fork 12.8k
/
Copy pathcomplicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.types
96 lines (72 loc) · 2.67 KB
/
complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.types
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
=== tests/cases/compiler/complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts ===
interface TextChannel {
id: string;
>id : string
type: 'text';
>type : "text"
phoneNumber: string;
>phoneNumber : string
}
interface EmailChannel {
id: string;
>id : string
type: 'email';
>type : "email"
addres: string;
>addres : string
}
type Channel = TextChannel | EmailChannel;
>Channel : Channel
export type ChannelType = Channel extends { type: infer R } ? R : never;
>ChannelType : "text" | "email"
>type : R
type Omit<T, K extends keyof T> = Pick<
>Omit : Omit<T, K>
T,
({ [P in keyof T]: P } & { [P in K]: never } & { [x: string]: never })[keyof T]
>x : string
>;
type ChannelOfType<T extends ChannelType, A = Channel> = A extends { type: T }
>ChannelOfType : ChannelOfType<T, A>
>type : T
? A
: never;
export type NewChannel<T extends Channel> = Pick<T, 'type'> &
>NewChannel : NewChannel<T>
Partial<Omit<T, 'type' | 'id'>> & { localChannelId: string };
>localChannelId : string
export function makeNewChannel<T extends ChannelType>(type: T): NewChannel<ChannelOfType<T>> {
>makeNewChannel : <T extends "text" | "email">(type: T) => NewChannel<ChannelOfType<T>>
>type : T
const localChannelId = `blahblahblah`;
>localChannelId : "blahblahblah"
>`blahblahblah` : "blahblahblah"
return { type, localChannelId };
>{ type, localChannelId } : { type: T; localChannelId: string; }
>type : T
>localChannelId : string
}
const newTextChannel = makeNewChannel('text');
>newTextChannel : NewChannel<TextChannel>
>makeNewChannel('text') : NewChannel<TextChannel>
>makeNewChannel : <T extends "text" | "email">(type: T) => NewChannel<ChannelOfType<T, TextChannel> | ChannelOfType<T, EmailChannel>>
>'text' : "text"
// This should work
newTextChannel.phoneNumber = '613-555-1234';
>newTextChannel.phoneNumber = '613-555-1234' : "613-555-1234"
>newTextChannel.phoneNumber : string
>newTextChannel : NewChannel<TextChannel>
>phoneNumber : string
>'613-555-1234' : "613-555-1234"
const newTextChannel2 : NewChannel<TextChannel> = makeNewChannel('text');
>newTextChannel2 : NewChannel<TextChannel>
>makeNewChannel('text') : NewChannel<TextChannel>
>makeNewChannel : <T extends "text" | "email">(type: T) => NewChannel<ChannelOfType<T, TextChannel> | ChannelOfType<T, EmailChannel>>
>'text' : "text"
// Compare with this, which ofc works.
newTextChannel2.phoneNumber = '613-555-1234';
>newTextChannel2.phoneNumber = '613-555-1234' : "613-555-1234"
>newTextChannel2.phoneNumber : string
>newTextChannel2 : NewChannel<TextChannel>
>phoneNumber : string
>'613-555-1234' : "613-555-1234"