Skip to content

Commit 2f33b46

Browse files
committed
Improve relationship check for mapped type sources under exactOptionalPropertyTypes
1 parent 56a0825 commit 2f33b46

4 files changed

+177
-7
lines changed

src/compiler/checker.ts

+21-2
Original file line numberDiff line numberDiff line change
@@ -12337,7 +12337,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1233712337
}
1233812338

1233912339
function getNonMissingTypeOfSymbol(symbol: Symbol) {
12340-
return removeMissingType(getTypeOfSymbol(symbol), !!(symbol.flags & SymbolFlags.Optional));
12340+
let type = getTypeOfSymbol(symbol);
12341+
if (exactOptionalPropertyTypes) {
12342+
const checkFlags = getCheckFlags(symbol);
12343+
if (checkFlags & CheckFlags.Mapped) {
12344+
const mappedType = (symbol as MappedSymbol).links.mappedType;
12345+
const keyType = (symbol as MappedSymbol).links.keyType;
12346+
const modifiersType = getModifiersTypeFromMappedType(mappedType);
12347+
if (modifiersType !== unknownType) {
12348+
type = mapType(type, t => {
12349+
if (!(t.flags & TypeFlags.IndexedAccess) || (t as IndexedAccessType).objectType !== modifiersType || (t as IndexedAccessType).indexType !== keyType) {
12350+
return t;
12351+
}
12352+
return getIndexedAccessType(modifiersType, keyType, AccessFlags.NonMissing, /*accessNode*/ undefined, t.aliasSymbol, t.aliasTypeArguments);
12353+
});
12354+
}
12355+
}
12356+
}
12357+
return removeMissingType(type, !!(symbol.flags & SymbolFlags.Optional));
1234112358
}
1234212359

1234312360
function isReferenceToSomeType(type: Type, targets: readonly Type[]) {
@@ -18630,7 +18647,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1863018647
return autoType;
1863118648
}
1863218649
}
18633-
const propType = accessFlags & AccessFlags.Writing ? getWriteTypeOfSymbol(prop) : getTypeOfSymbol(prop);
18650+
const propType = accessFlags & AccessFlags.Writing ?
18651+
getWriteTypeOfSymbol(prop) :
18652+
removeMissingType(getTypeOfSymbol(prop), !!(prop.flags & SymbolFlags.Optional && accessFlags & AccessFlags.NonMissing));
1863418653
return accessExpression && getAssignmentTargetKind(accessExpression) !== AssignmentKind.Definite ? getFlowTypeOfReference(accessExpression, propType) :
1863518654
accessNode && isIndexedAccessTypeNode(accessNode) && containsMissingType(propType) ? getUnionType([propType, undefinedType]) :
1863618655
propType;

src/compiler/types.ts

+6-5
Original file line numberDiff line numberDiff line change
@@ -6835,11 +6835,12 @@ export const enum AccessFlags {
68356835
Writing = 1 << 2,
68366836
CacheSymbol = 1 << 3,
68376837
AllowMissing = 1 << 4,
6838-
ExpressionPosition = 1 << 5,
6839-
ReportDeprecated = 1 << 6,
6840-
SuppressNoImplicitAnyError = 1 << 7,
6841-
Contextual = 1 << 8,
6842-
Persistent = IncludeUndefined,
6838+
NonMissing = 1 << 5,
6839+
ExpressionPosition = 1 << 6,
6840+
ReportDeprecated = 1 << 7,
6841+
SuppressNoImplicitAnyError = 1 << 8,
6842+
Contextual = 1 << 9,
6843+
Persistent = IncludeUndefined | NonMissing,
68436844
}
68446845

68456846
// Indexed access types (TypeFlags.IndexedAccess)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//// [tests/cases/compiler/mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts] ////
2+
3+
=== mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/60233
5+
6+
type T = {
7+
>T : Symbol(T, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 0, 0))
8+
9+
foo?: true;
10+
>foo : Symbol(foo, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 2, 10))
11+
12+
bar?: true;
13+
>bar : Symbol(bar, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 3, 13))
14+
15+
};
16+
17+
type WrappedT<t extends T> = [t];
18+
>WrappedT : Symbol(WrappedT, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 5, 2))
19+
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 7, 14))
20+
>T : Symbol(T, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 0, 0))
21+
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 7, 14))
22+
23+
type OmitBarFromWrapped<t> = t extends WrappedT<infer inner>
24+
>OmitBarFromWrapped : Symbol(OmitBarFromWrapped, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 7, 33))
25+
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 9, 24))
26+
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 9, 24))
27+
>WrappedT : Symbol(WrappedT, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 5, 2))
28+
>inner : Symbol(inner, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 9, 53))
29+
30+
? WrappedT<Omit<inner, "bar">>
31+
>WrappedT : Symbol(WrappedT, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 5, 2))
32+
>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --))
33+
>inner : Symbol(inner, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 9, 53))
34+
35+
: never;
36+
37+
type OmitHomomorphicFromWrapped<t> = t extends WrappedT<infer inner>
38+
>OmitHomomorphicFromWrapped : Symbol(OmitHomomorphicFromWrapped, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 11, 10))
39+
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 13, 32))
40+
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 13, 32))
41+
>WrappedT : Symbol(WrappedT, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 5, 2))
42+
>inner : Symbol(inner, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 13, 61))
43+
44+
? WrappedT<HomomorphicOmit<inner, "bar">>
45+
>WrappedT : Symbol(WrappedT, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 5, 2))
46+
>HomomorphicOmit : Symbol(HomomorphicOmit, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 15, 10))
47+
>inner : Symbol(inner, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 13, 61))
48+
49+
: never;
50+
51+
type HomomorphicOmit<t, keyToOmit> = {
52+
>HomomorphicOmit : Symbol(HomomorphicOmit, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 15, 10))
53+
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 17, 21))
54+
>keyToOmit : Symbol(keyToOmit, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 17, 23))
55+
56+
[k in keyof t as k extends keyToOmit ? never : k]: t[k];
57+
>k : Symbol(k, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 18, 3))
58+
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 17, 21))
59+
>k : Symbol(k, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 18, 3))
60+
>keyToOmit : Symbol(keyToOmit, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 17, 23))
61+
>k : Symbol(k, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 18, 3))
62+
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 17, 21))
63+
>k : Symbol(k, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 18, 3))
64+
65+
};
66+
67+
type OmitHomomorphicFromWrappedConformed<t> = t extends WrappedT<infer inner>
68+
>OmitHomomorphicFromWrappedConformed : Symbol(OmitHomomorphicFromWrappedConformed, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 19, 2))
69+
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 21, 41))
70+
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 21, 41))
71+
>WrappedT : Symbol(WrappedT, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 5, 2))
72+
>inner : Symbol(inner, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 21, 70))
73+
74+
? WrappedT<conform<HomomorphicOmit<inner, "bar">, T>>
75+
>WrappedT : Symbol(WrappedT, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 5, 2))
76+
>conform : Symbol(conform, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 23, 10))
77+
>HomomorphicOmit : Symbol(HomomorphicOmit, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 15, 10))
78+
>inner : Symbol(inner, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 21, 70))
79+
>T : Symbol(T, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 0, 0))
80+
81+
: never;
82+
83+
type conform<t, base> = t extends base ? t : base;
84+
>conform : Symbol(conform, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 23, 10))
85+
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 25, 13))
86+
>base : Symbol(base, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 25, 15))
87+
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 25, 13))
88+
>base : Symbol(base, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 25, 15))
89+
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 25, 13))
90+
>base : Symbol(base, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 25, 15))
91+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//// [tests/cases/compiler/mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts] ////
2+
3+
=== mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/60233
5+
6+
type T = {
7+
>T : T
8+
> : ^
9+
10+
foo?: true;
11+
>foo : true | undefined
12+
> : ^^^^^^^^^^^^^^^^
13+
>true : true
14+
> : ^^^^
15+
16+
bar?: true;
17+
>bar : true | undefined
18+
> : ^^^^^^^^^^^^^^^^
19+
>true : true
20+
> : ^^^^
21+
22+
};
23+
24+
type WrappedT<t extends T> = [t];
25+
>WrappedT : WrappedT<t>
26+
> : ^^^^^^^^^^^
27+
28+
type OmitBarFromWrapped<t> = t extends WrappedT<infer inner>
29+
>OmitBarFromWrapped : OmitBarFromWrapped<t>
30+
> : ^^^^^^^^^^^^^^^^^^^^^
31+
32+
? WrappedT<Omit<inner, "bar">>
33+
: never;
34+
35+
type OmitHomomorphicFromWrapped<t> = t extends WrappedT<infer inner>
36+
>OmitHomomorphicFromWrapped : OmitHomomorphicFromWrapped<t>
37+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
38+
39+
? WrappedT<HomomorphicOmit<inner, "bar">>
40+
: never;
41+
42+
type HomomorphicOmit<t, keyToOmit> = {
43+
>HomomorphicOmit : HomomorphicOmit<t, keyToOmit>
44+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
45+
46+
[k in keyof t as k extends keyToOmit ? never : k]: t[k];
47+
};
48+
49+
type OmitHomomorphicFromWrappedConformed<t> = t extends WrappedT<infer inner>
50+
>OmitHomomorphicFromWrappedConformed : OmitHomomorphicFromWrappedConformed<t>
51+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
52+
53+
? WrappedT<conform<HomomorphicOmit<inner, "bar">, T>>
54+
: never;
55+
56+
type conform<t, base> = t extends base ? t : base;
57+
>conform : conform<t, base>
58+
> : ^^^^^^^^^^^^^^^^
59+

0 commit comments

Comments
 (0)