Skip to content

Commit d405662

Browse files
authored
Explicitly encode keyof behaviors for never and unknown into getIndexType (#30753)
* Explicitly encode keyof behaviors for never and unknown into getIndexType * Merge similar cases
1 parent 3dc78b6 commit d405662

11 files changed

+1707
-1291
lines changed

src/compiler/checker.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9841,7 +9841,8 @@ namespace ts {
98419841
maybeTypeOfKind(type, TypeFlags.InstantiableNonPrimitive) ? getIndexTypeForGenericType(<InstantiableType | UnionOrIntersectionType>type, stringsOnly) :
98429842
getObjectFlags(type) & ObjectFlags.Mapped ? filterType(getConstraintTypeFromMappedType(<MappedType>type), t => !(noIndexSignatures && t.flags & (TypeFlags.Any | TypeFlags.String | TypeFlags.Number))) :
98439843
type === wildcardType ? wildcardType :
9844-
type.flags & TypeFlags.Any ? keyofConstraintType :
9844+
type.flags & TypeFlags.Unknown ? neverType :
9845+
type.flags & (TypeFlags.Any | TypeFlags.Never) ? keyofConstraintType :
98459846
stringsOnly ? !noIndexSignatures && getIndexInfoOfType(type, IndexKind.String) ? stringType : getLiteralTypeFromProperties(type, TypeFlags.StringLiteral) :
98469847
!noIndexSignatures && getIndexInfoOfType(type, IndexKind.String) ? getUnionType([stringType, numberType, getLiteralTypeFromProperties(type, TypeFlags.UniqueESSymbol)]) :
98479848
!noIndexSignatures && getNonEnumNumberIndexInfo(type) ? getUnionType([numberType, getLiteralTypeFromProperties(type, TypeFlags.StringLiteral | TypeFlags.UniqueESSymbol)]) :
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
tests/cases/compiler/complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts(33,5): error TS2322: Type '{ type: T; localChannelId: string; }' is not assignable to type 'NewChannel<ChannelOfType<T, TextChannel> | ChannelOfType<T, EmailChannel>>'.
2+
Type '{ type: T; localChannelId: string; }' is not assignable to type 'Pick<ChannelOfType<T, TextChannel> | ChannelOfType<T, EmailChannel>, "type">'.
3+
Types of property 'type' are incompatible.
4+
Type 'T' is not assignable to type 'ChannelOfType<T, TextChannel>["type"] & ChannelOfType<T, EmailChannel>["type"]'.
5+
Type '"text" | "email"' is not assignable to type 'ChannelOfType<T, TextChannel>["type"] & ChannelOfType<T, EmailChannel>["type"]'.
6+
Type '"text"' is not assignable to type 'ChannelOfType<T, TextChannel>["type"] & ChannelOfType<T, EmailChannel>["type"]'.
7+
Type '"text"' is not assignable to type 'ChannelOfType<T, TextChannel>["type"]'.
8+
Type 'T' is not assignable to type 'ChannelOfType<T, TextChannel>["type"]'.
9+
Type '"text" | "email"' is not assignable to type 'ChannelOfType<T, TextChannel>["type"]'.
10+
Type '"text"' is not assignable to type 'ChannelOfType<T, TextChannel>["type"]'.
11+
Type '"text"' is not assignable to type 'T & "text"'.
12+
Type '"text"' is not assignable to type 'T'.
13+
Type 'T' is not assignable to type 'T & "text"'.
14+
Type '"text" | "email"' is not assignable to type 'T & "text"'.
15+
Type '"text"' is not assignable to type 'T & "text"'.
16+
Type '"text"' is not assignable to type 'T'.
17+
Type 'T' is not assignable to type '"text"'.
18+
Type '"text" | "email"' is not assignable to type '"text"'.
19+
Type '"email"' is not assignable to type '"text"'.
20+
21+
22+
==== tests/cases/compiler/complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts (1 errors) ====
23+
interface TextChannel {
24+
id: string;
25+
type: 'text';
26+
phoneNumber: string;
27+
}
28+
29+
interface EmailChannel {
30+
id: string;
31+
type: 'email';
32+
addres: string;
33+
}
34+
35+
type Channel = TextChannel | EmailChannel;
36+
37+
export type ChannelType = Channel extends { type: infer R } ? R : never;
38+
39+
type Omit<T, K extends keyof T> = Pick<
40+
T,
41+
({ [P in keyof T]: P } & { [P in K]: never } & { [x: string]: never })[keyof T]
42+
>;
43+
44+
type ChannelOfType<T extends ChannelType, A = Channel> = A extends { type: T }
45+
? A
46+
: never;
47+
48+
49+
export type NewChannel<T extends Channel> = Pick<T, 'type'> &
50+
Partial<Omit<T, 'type' | 'id'>> & { localChannelId: string };
51+
52+
53+
export function makeNewChannel<T extends ChannelType>(type: T): NewChannel<ChannelOfType<T>> {
54+
const localChannelId = `blahblahblah`;
55+
return { type, localChannelId };
56+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
57+
!!! error TS2322: Type '{ type: T; localChannelId: string; }' is not assignable to type 'NewChannel<ChannelOfType<T, TextChannel> | ChannelOfType<T, EmailChannel>>'.
58+
!!! error TS2322: Type '{ type: T; localChannelId: string; }' is not assignable to type 'Pick<ChannelOfType<T, TextChannel> | ChannelOfType<T, EmailChannel>, "type">'.
59+
!!! error TS2322: Types of property 'type' are incompatible.
60+
!!! error TS2322: Type 'T' is not assignable to type 'ChannelOfType<T, TextChannel>["type"] & ChannelOfType<T, EmailChannel>["type"]'.
61+
!!! error TS2322: Type '"text" | "email"' is not assignable to type 'ChannelOfType<T, TextChannel>["type"] & ChannelOfType<T, EmailChannel>["type"]'.
62+
!!! error TS2322: Type '"text"' is not assignable to type 'ChannelOfType<T, TextChannel>["type"] & ChannelOfType<T, EmailChannel>["type"]'.
63+
!!! error TS2322: Type '"text"' is not assignable to type 'ChannelOfType<T, TextChannel>["type"]'.
64+
!!! error TS2322: Type 'T' is not assignable to type 'ChannelOfType<T, TextChannel>["type"]'.
65+
!!! error TS2322: Type '"text" | "email"' is not assignable to type 'ChannelOfType<T, TextChannel>["type"]'.
66+
!!! error TS2322: Type '"text"' is not assignable to type 'ChannelOfType<T, TextChannel>["type"]'.
67+
!!! error TS2322: Type '"text"' is not assignable to type 'T & "text"'.
68+
!!! error TS2322: Type '"text"' is not assignable to type 'T'.
69+
!!! error TS2322: Type 'T' is not assignable to type 'T & "text"'.
70+
!!! error TS2322: Type '"text" | "email"' is not assignable to type 'T & "text"'.
71+
!!! error TS2322: Type '"text"' is not assignable to type 'T & "text"'.
72+
!!! error TS2322: Type '"text"' is not assignable to type 'T'.
73+
!!! error TS2322: Type 'T' is not assignable to type '"text"'.
74+
!!! error TS2322: Type '"text" | "email"' is not assignable to type '"text"'.
75+
!!! error TS2322: Type '"email"' is not assignable to type '"text"'.
76+
}
77+
78+
const newTextChannel = makeNewChannel('text');
79+
// This should work
80+
newTextChannel.phoneNumber = '613-555-1234';
81+
82+
const newTextChannel2 : NewChannel<TextChannel> = makeNewChannel('text');
83+
// Compare with this, which ofc works.
84+
newTextChannel2.phoneNumber = '613-555-1234';
85+
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//// [complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts]
2+
interface TextChannel {
3+
id: string;
4+
type: 'text';
5+
phoneNumber: string;
6+
}
7+
8+
interface EmailChannel {
9+
id: string;
10+
type: 'email';
11+
addres: string;
12+
}
13+
14+
type Channel = TextChannel | EmailChannel;
15+
16+
export type ChannelType = Channel extends { type: infer R } ? R : never;
17+
18+
type Omit<T, K extends keyof T> = Pick<
19+
T,
20+
({ [P in keyof T]: P } & { [P in K]: never } & { [x: string]: never })[keyof T]
21+
>;
22+
23+
type ChannelOfType<T extends ChannelType, A = Channel> = A extends { type: T }
24+
? A
25+
: never;
26+
27+
28+
export type NewChannel<T extends Channel> = Pick<T, 'type'> &
29+
Partial<Omit<T, 'type' | 'id'>> & { localChannelId: string };
30+
31+
32+
export function makeNewChannel<T extends ChannelType>(type: T): NewChannel<ChannelOfType<T>> {
33+
const localChannelId = `blahblahblah`;
34+
return { type, localChannelId };
35+
}
36+
37+
const newTextChannel = makeNewChannel('text');
38+
// This should work
39+
newTextChannel.phoneNumber = '613-555-1234';
40+
41+
const newTextChannel2 : NewChannel<TextChannel> = makeNewChannel('text');
42+
// Compare with this, which ofc works.
43+
newTextChannel2.phoneNumber = '613-555-1234';
44+
45+
46+
//// [complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.js]
47+
"use strict";
48+
exports.__esModule = true;
49+
function makeNewChannel(type) {
50+
var localChannelId = "blahblahblah";
51+
return { type: type, localChannelId: localChannelId };
52+
}
53+
exports.makeNewChannel = makeNewChannel;
54+
var newTextChannel = makeNewChannel('text');
55+
// This should work
56+
newTextChannel.phoneNumber = '613-555-1234';
57+
var newTextChannel2 = makeNewChannel('text');
58+
// Compare with this, which ofc works.
59+
newTextChannel2.phoneNumber = '613-555-1234';
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
=== tests/cases/compiler/complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts ===
2+
interface TextChannel {
3+
>TextChannel : Symbol(TextChannel, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 0, 0))
4+
5+
id: string;
6+
>id : Symbol(TextChannel.id, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 0, 23))
7+
8+
type: 'text';
9+
>type : Symbol(TextChannel.type, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 1, 15))
10+
11+
phoneNumber: string;
12+
>phoneNumber : Symbol(TextChannel.phoneNumber, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 2, 17))
13+
}
14+
15+
interface EmailChannel {
16+
>EmailChannel : Symbol(EmailChannel, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 4, 1))
17+
18+
id: string;
19+
>id : Symbol(EmailChannel.id, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 6, 24))
20+
21+
type: 'email';
22+
>type : Symbol(EmailChannel.type, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 7, 15))
23+
24+
addres: string;
25+
>addres : Symbol(EmailChannel.addres, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 8, 18))
26+
}
27+
28+
type Channel = TextChannel | EmailChannel;
29+
>Channel : Symbol(Channel, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 10, 1))
30+
>TextChannel : Symbol(TextChannel, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 0, 0))
31+
>EmailChannel : Symbol(EmailChannel, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 4, 1))
32+
33+
export type ChannelType = Channel extends { type: infer R } ? R : never;
34+
>ChannelType : Symbol(ChannelType, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 12, 42))
35+
>Channel : Symbol(Channel, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 10, 1))
36+
>type : Symbol(type, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 14, 43))
37+
>R : Symbol(R, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 14, 55))
38+
>R : Symbol(R, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 14, 55))
39+
40+
type Omit<T, K extends keyof T> = Pick<
41+
>Omit : Symbol(Omit, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 14, 72))
42+
>T : Symbol(T, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 16, 10))
43+
>K : Symbol(K, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 16, 12))
44+
>T : Symbol(T, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 16, 10))
45+
>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --))
46+
47+
T,
48+
>T : Symbol(T, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 16, 10))
49+
50+
({ [P in keyof T]: P } & { [P in K]: never } & { [x: string]: never })[keyof T]
51+
>P : Symbol(P, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 18, 8))
52+
>T : Symbol(T, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 16, 10))
53+
>P : Symbol(P, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 18, 8))
54+
>P : Symbol(P, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 18, 32))
55+
>K : Symbol(K, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 16, 12))
56+
>x : Symbol(x, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 18, 54))
57+
>T : Symbol(T, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 16, 10))
58+
59+
>;
60+
61+
type ChannelOfType<T extends ChannelType, A = Channel> = A extends { type: T }
62+
>ChannelOfType : Symbol(ChannelOfType, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 19, 2))
63+
>T : Symbol(T, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 21, 19))
64+
>ChannelType : Symbol(ChannelType, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 12, 42))
65+
>A : Symbol(A, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 21, 41))
66+
>Channel : Symbol(Channel, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 10, 1))
67+
>A : Symbol(A, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 21, 41))
68+
>type : Symbol(type, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 21, 68))
69+
>T : Symbol(T, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 21, 19))
70+
71+
? A
72+
>A : Symbol(A, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 21, 41))
73+
74+
: never;
75+
76+
77+
export type NewChannel<T extends Channel> = Pick<T, 'type'> &
78+
>NewChannel : Symbol(NewChannel, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 23, 12))
79+
>T : Symbol(T, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 26, 23))
80+
>Channel : Symbol(Channel, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 10, 1))
81+
>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --))
82+
>T : Symbol(T, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 26, 23))
83+
84+
Partial<Omit<T, 'type' | 'id'>> & { localChannelId: string };
85+
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
86+
>Omit : Symbol(Omit, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 14, 72))
87+
>T : Symbol(T, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 26, 23))
88+
>localChannelId : Symbol(localChannelId, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 27, 39))
89+
90+
91+
export function makeNewChannel<T extends ChannelType>(type: T): NewChannel<ChannelOfType<T>> {
92+
>makeNewChannel : Symbol(makeNewChannel, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 27, 65))
93+
>T : Symbol(T, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 30, 31))
94+
>ChannelType : Symbol(ChannelType, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 12, 42))
95+
>type : Symbol(type, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 30, 54))
96+
>T : Symbol(T, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 30, 31))
97+
>NewChannel : Symbol(NewChannel, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 23, 12))
98+
>ChannelOfType : Symbol(ChannelOfType, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 19, 2))
99+
>T : Symbol(T, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 30, 31))
100+
101+
const localChannelId = `blahblahblah`;
102+
>localChannelId : Symbol(localChannelId, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 31, 9))
103+
104+
return { type, localChannelId };
105+
>type : Symbol(type, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 32, 12))
106+
>localChannelId : Symbol(localChannelId, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 32, 18))
107+
}
108+
109+
const newTextChannel = makeNewChannel('text');
110+
>newTextChannel : Symbol(newTextChannel, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 35, 5))
111+
>makeNewChannel : Symbol(makeNewChannel, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 27, 65))
112+
113+
// This should work
114+
newTextChannel.phoneNumber = '613-555-1234';
115+
>newTextChannel.phoneNumber : Symbol(phoneNumber, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 2, 17))
116+
>newTextChannel : Symbol(newTextChannel, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 35, 5))
117+
>phoneNumber : Symbol(phoneNumber, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 2, 17))
118+
119+
const newTextChannel2 : NewChannel<TextChannel> = makeNewChannel('text');
120+
>newTextChannel2 : Symbol(newTextChannel2, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 39, 5))
121+
>NewChannel : Symbol(NewChannel, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 23, 12))
122+
>TextChannel : Symbol(TextChannel, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 0, 0))
123+
>makeNewChannel : Symbol(makeNewChannel, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 27, 65))
124+
125+
// Compare with this, which ofc works.
126+
newTextChannel2.phoneNumber = '613-555-1234';
127+
>newTextChannel2.phoneNumber : Symbol(phoneNumber, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 2, 17))
128+
>newTextChannel2 : Symbol(newTextChannel2, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 39, 5))
129+
>phoneNumber : Symbol(phoneNumber, Decl(complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts, 2, 17))
130+
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
=== tests/cases/compiler/complicatedIndexedAccessKeyofReliesOnKeyofNeverUpperBound.ts ===
2+
interface TextChannel {
3+
id: string;
4+
>id : string
5+
6+
type: 'text';
7+
>type : "text"
8+
9+
phoneNumber: string;
10+
>phoneNumber : string
11+
}
12+
13+
interface EmailChannel {
14+
id: string;
15+
>id : string
16+
17+
type: 'email';
18+
>type : "email"
19+
20+
addres: string;
21+
>addres : string
22+
}
23+
24+
type Channel = TextChannel | EmailChannel;
25+
>Channel : Channel
26+
27+
export type ChannelType = Channel extends { type: infer R } ? R : never;
28+
>ChannelType : "text" | "email"
29+
>type : R
30+
31+
type Omit<T, K extends keyof T> = Pick<
32+
>Omit : Pick<T, ({ [P in keyof T]: P; } & { [P in K]: never; } & { [x: string]: never; })[keyof T]>
33+
34+
T,
35+
({ [P in keyof T]: P } & { [P in K]: never } & { [x: string]: never })[keyof T]
36+
>x : string
37+
38+
>;
39+
40+
type ChannelOfType<T extends ChannelType, A = Channel> = A extends { type: T }
41+
>ChannelOfType : ChannelOfType<T, A>
42+
>type : T
43+
44+
? A
45+
: never;
46+
47+
48+
export type NewChannel<T extends Channel> = Pick<T, 'type'> &
49+
>NewChannel : NewChannel<T>
50+
51+
Partial<Omit<T, 'type' | 'id'>> & { localChannelId: string };
52+
>localChannelId : string
53+
54+
55+
export function makeNewChannel<T extends ChannelType>(type: T): NewChannel<ChannelOfType<T>> {
56+
>makeNewChannel : <T extends "text" | "email">(type: T) => NewChannel<ChannelOfType<T, TextChannel> | ChannelOfType<T, EmailChannel>>
57+
>type : T
58+
59+
const localChannelId = `blahblahblah`;
60+
>localChannelId : "blahblahblah"
61+
>`blahblahblah` : "blahblahblah"
62+
63+
return { type, localChannelId };
64+
>{ type, localChannelId } : { type: T; localChannelId: string; }
65+
>type : T
66+
>localChannelId : string
67+
}
68+
69+
const newTextChannel = makeNewChannel('text');
70+
>newTextChannel : NewChannel<TextChannel>
71+
>makeNewChannel('text') : NewChannel<TextChannel>
72+
>makeNewChannel : <T extends "text" | "email">(type: T) => NewChannel<ChannelOfType<T, TextChannel> | ChannelOfType<T, EmailChannel>>
73+
>'text' : "text"
74+
75+
// This should work
76+
newTextChannel.phoneNumber = '613-555-1234';
77+
>newTextChannel.phoneNumber = '613-555-1234' : "613-555-1234"
78+
>newTextChannel.phoneNumber : string
79+
>newTextChannel : NewChannel<TextChannel>
80+
>phoneNumber : string
81+
>'613-555-1234' : "613-555-1234"
82+
83+
const newTextChannel2 : NewChannel<TextChannel> = makeNewChannel('text');
84+
>newTextChannel2 : NewChannel<TextChannel>
85+
>makeNewChannel('text') : NewChannel<TextChannel>
86+
>makeNewChannel : <T extends "text" | "email">(type: T) => NewChannel<ChannelOfType<T, TextChannel> | ChannelOfType<T, EmailChannel>>
87+
>'text' : "text"
88+
89+
// Compare with this, which ofc works.
90+
newTextChannel2.phoneNumber = '613-555-1234';
91+
>newTextChannel2.phoneNumber = '613-555-1234' : "613-555-1234"
92+
>newTextChannel2.phoneNumber : string
93+
>newTextChannel2 : NewChannel<TextChannel>
94+
>phoneNumber : string
95+
>'613-555-1234' : "613-555-1234"
96+

0 commit comments

Comments
 (0)