Skip to content

Commit 7a1c5b7

Browse files
authored
Avoid expensive relationship checking in mapped type member resolution (#36754)
* Avoid expensive relationship checking in mapped type member resolution * Accept new baselines
1 parent e435054 commit 7a1c5b7

6 files changed

+23
-23
lines changed

src/compiler/checker.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -9590,7 +9590,7 @@ namespace ts {
95909590
// When creating an optional property in strictNullChecks mode, if 'undefined' isn't assignable to the
95919591
// type, we include 'undefined' in the type. Similarly, when creating a non-optional property in strictNullChecks
95929592
// mode, if the underlying property is optional we remove 'undefined' from the type.
9593-
prop.type = strictNullChecks && isOptional && !isTypeAssignableTo(undefinedType, propType) ? getOptionalType(propType) :
9593+
prop.type = strictNullChecks && isOptional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType) :
95949594
strictNullChecks && !isOptional && modifiersProp && modifiersProp.flags & SymbolFlags.Optional ? getTypeWithFacts(propType, TypeFacts.NEUndefined) :
95959595
propType;
95969596
if (modifiersProp) {
@@ -13695,7 +13695,7 @@ namespace ts {
1369513695
const templateMapper = combineTypeMappers(mapper, createTypeMapper([getTypeParameterFromMappedType(type)], [key]));
1369613696
const propType = instantiateType(getTemplateTypeFromMappedType(<MappedType>type.target || type), templateMapper);
1369713697
const modifiers = getMappedTypeModifiers(type);
13698-
return strictNullChecks && modifiers & MappedTypeModifiers.IncludeOptional && !isTypeAssignableTo(undefinedType, propType) ? getOptionalType(propType) :
13698+
return strictNullChecks && modifiers & MappedTypeModifiers.IncludeOptional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType) :
1369913699
strictNullChecks && modifiers & MappedTypeModifiers.ExcludeOptional && isOptional ? getTypeWithFacts(propType, TypeFacts.NEUndefined) :
1370013700
propType;
1370113701
}

tests/baselines/reference/definiteAssignmentOfDestructuredVariable.types

+6-6
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,20 @@ class C<T extends Options> {
1818
>method : () => void
1919

2020
let { a, b } = this.foo;
21-
>a : T["a"]
21+
>a : T["a"] | undefined
2222
>b : T["b"]
2323
>this.foo : { [P in keyof T]: T[P]; }
2424
>this : this
2525
>foo : { [P in keyof T]: T[P]; }
2626

2727
!(a && b);
28-
>!(a && b) : false
29-
>(a && b) : T["b"]
30-
>a && b : T["b"]
31-
>a : T["a"]
28+
>!(a && b) : boolean
29+
>(a && b) : T["b"] | undefined
30+
>a && b : T["b"] | undefined
31+
>a : T["a"] | undefined
3232
>b : T["b"]
3333

3434
a;
35-
>a : T["a"]
35+
>a : T["a"] | undefined
3636
}
3737
}

tests/baselines/reference/strictNullNotNullIndexTypeNoLib.types

+4-4
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ class Test<T extends A> {
2020
this.attrs.params!.name;
2121
>this.attrs.params!.name : any
2222
>this.attrs.params! : T["params"]
23-
>this.attrs.params : T["params"]
23+
>this.attrs.params : T["params"] | undefined
2424
>this.attrs : Readonly<T>
2525
>this : this
2626
>attrs : Readonly<T>
27-
>params : T["params"]
27+
>params : T["params"] | undefined
2828
>name : any
2929
}
3030
}
@@ -66,10 +66,10 @@ class Test2<T extends A> {
6666

6767
return this.attrs.params!; // Return type should maintain relationship with `T` after being not-null-asserted, ideally
6868
>this.attrs.params! : T["params"]
69-
>this.attrs.params : T["params"]
69+
>this.attrs.params : T["params"] | undefined
7070
>this.attrs : Readonly<T>
7171
>this : this
7272
>attrs : Readonly<T>
73-
>params : T["params"]
73+
>params : T["params"] | undefined
7474
}
7575
}

tests/baselines/reference/strictNullNotNullIndexTypeShouldWork.types

+4-4
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ class Test<T extends A> {
1717
this.attrs.params!.name;
1818
>this.attrs.params!.name : string
1919
>this.attrs.params! : NonNullable<T["params"]>
20-
>this.attrs.params : T["params"]
20+
>this.attrs.params : T["params"] | undefined
2121
>this.attrs : Readonly<T>
2222
>this : this
2323
>attrs : Readonly<T>
24-
>params : T["params"]
24+
>params : T["params"] | undefined
2525
>name : string
2626
}
2727
}
@@ -63,10 +63,10 @@ class Test2<T extends A> {
6363

6464
return this.attrs.params!; // Return type should maintain relationship with `T` after being not-null-asserted, ideally
6565
>this.attrs.params! : NonNullable<T["params"]>
66-
>this.attrs.params : T["params"]
66+
>this.attrs.params : T["params"] | undefined
6767
>this.attrs : Readonly<T>
6868
>this : this
6969
>attrs : Readonly<T>
70-
>params : T["params"]
70+
>params : T["params"] | undefined
7171
}
7272
}

tests/baselines/reference/typeVariableTypeGuards.types

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ class A<P extends Partial<Foo>> {
1616
>doSomething : () => void
1717

1818
this.props.foo && this.props.foo()
19-
>this.props.foo && this.props.foo() : void
20-
>this.props.foo : P["foo"]
19+
>this.props.foo && this.props.foo() : void | undefined
20+
>this.props.foo : P["foo"] | undefined
2121
>this.props : Readonly<P>
2222
>this : this
2323
>props : Readonly<P>
24-
>foo : P["foo"]
24+
>foo : P["foo"] | undefined
2525
>this.props.foo() : void
2626
>this.props.foo : () => void
2727
>this.props : Readonly<P>

tests/baselines/reference/voidReturnIndexUnionInference.types

+4-4
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,19 @@ function bad<P extends Props>(props: Readonly<P>) {
4343
safeInvoke(props.onFoo, "blah");
4444
>safeInvoke(props.onFoo, "blah") : boolean | undefined
4545
>safeInvoke : <A1, R>(func: ((arg1: A1) => R) | null | undefined, arg1: A1) => R | undefined
46-
>props.onFoo : P["onFoo"]
46+
>props.onFoo : P["onFoo"] | undefined
4747
>props : Readonly<P>
48-
>onFoo : P["onFoo"]
48+
>onFoo : P["onFoo"] | undefined
4949
>"blah" : "blah"
5050

5151
// ERROR HERE!!!
5252
// Type R in signature of safeInvoke incorrectly inferred as {} instead of void!
5353
safeInvoke(props.onBar, "blah");
5454
>safeInvoke(props.onBar, "blah") : void | undefined
5555
>safeInvoke : <A1, R>(func: ((arg1: A1) => R) | null | undefined, arg1: A1) => R | undefined
56-
>props.onBar : P["onBar"]
56+
>props.onBar : P["onBar"] | undefined
5757
>props : Readonly<P>
58-
>onBar : P["onBar"]
58+
>onBar : P["onBar"] | undefined
5959
>"blah" : "blah"
6060
}
6161

0 commit comments

Comments
 (0)