Skip to content

Commit 060f0b2

Browse files
committed
Use NonNullable type for nonnull types
1 parent d15b098 commit 060f0b2

File tree

3 files changed

+40
-14
lines changed

3 files changed

+40
-14
lines changed

src/compiler/checker.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,10 @@ namespace ts {
400400
let anyArrayType: Type;
401401
let autoArrayType: Type;
402402
let anyReadonlyArrayType: Type;
403+
let deferredGlobalNonNullableTypeAlias: Symbol;
404+
let deferredGlobalNonNullableTypeFallback: Type;
405+
let deferredGlobalNonNullableTypeFallbackInstantiationCache: Map<Type>;
406+
let deferredGlobalNonNullableTypeParameterFallback: TypeParameter;
403407

404408
// The library files are only loaded when the feature is used.
405409
// This allows users to just specify library files they want to used through --lib
@@ -11037,8 +11041,31 @@ namespace ts {
1103711041
return type.flags & TypeFlags.Undefined ? type : getUnionType([type, undefinedType]);
1103811042
}
1103911043

11044+
function getGlobalNonNullableTypeInstantiation(type: Type) {
11045+
if (!deferredGlobalNonNullableTypeAlias) {
11046+
deferredGlobalNonNullableTypeAlias = getGlobalSymbol("NonNullable" as __String, SymbolFlags.TypeAlias, /*diagnostic*/ undefined) || unknownSymbol;
11047+
}
11048+
// Use NonNullable global type alias if available to improve quick info/declaration emit
11049+
if (deferredGlobalNonNullableTypeAlias !== unknownSymbol) {
11050+
return getTypeAliasInstantiation(deferredGlobalNonNullableTypeAlias, [type]);
11051+
}
11052+
if (!deferredGlobalNonNullableTypeFallback) {
11053+
const p = deferredGlobalNonNullableTypeParameterFallback = createType(TypeFlags.TypeParameter) as TypeParameter;
11054+
deferredGlobalNonNullableTypeFallback = getConditionalType(p, getUnionType([nullType, undefinedType]), neverType, p, /*inferTypeParameters*/ undefined, /*target*/ undefined, /*mapper*/ undefined, /*alias*/ undefined, /*aliasTypeArguments*/ undefined);
11055+
deferredGlobalNonNullableTypeFallbackInstantiationCache = createMap();
11056+
}
11057+
// Fallback to manufacturing an anonymous conditional type instantiation
11058+
const args = [type];
11059+
const id = getTypeListId(args);
11060+
let instantiation = deferredGlobalNonNullableTypeFallbackInstantiationCache.get(id);
11061+
if (!instantiation) {
11062+
deferredGlobalNonNullableTypeFallbackInstantiationCache.set(id, instantiation = instantiateType(deferredGlobalNonNullableTypeFallback, createTypeMapper([deferredGlobalNonNullableTypeParameterFallback], [type])));
11063+
}
11064+
return instantiation;
11065+
}
11066+
1104011067
function getNonNullableType(type: Type): Type {
11041-
return strictNullChecks ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type;
11068+
return strictNullChecks ? getGlobalNonNullableTypeInstantiation(type) : type;
1104211069
}
1104311070

1104411071
/**
@@ -13314,7 +13341,6 @@ namespace ts {
1331413341
return parent.kind === SyntaxKind.PropertyAccessExpression ||
1331513342
parent.kind === SyntaxKind.CallExpression && (<CallExpression>parent).expression === node ||
1331613343
parent.kind === SyntaxKind.ElementAccessExpression && (<ElementAccessExpression>parent).expression === node ||
13317-
parent.kind === SyntaxKind.NonNullExpression ||
1331813344
parent.kind === SyntaxKind.BindingElement && (<BindingElement>parent).name === node && !!(<BindingElement>parent).initializer;
1331913345
}
1332013346

tests/baselines/reference/nonNullParameterExtendingStringAssignableToString.types

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,18 @@ function fn<T extends string | undefined, U extends string>(one: T, two: U) {
2323
foo(one!);
2424
>foo(one!) : void
2525
>foo : (p: string) => void
26-
>one! : string
27-
>one : string | undefined
26+
>one! : NonNullable<T>
27+
>one : T
2828

2929
foo(two!);
3030
>foo(two!) : void
3131
>foo : (p: string) => void
32-
>two! : U
32+
>two! : NonNullable<U>
3333
>two : U
3434

3535
foo(three!); // this line is the important one
3636
>foo(three!) : void
3737
>foo : (p: string) => void
38-
>three! : string
39-
>three : string
38+
>three! : NonNullable<T> | NonNullable<U>
39+
>three : T | U
4040
}

tests/baselines/reference/strictNullNotNullIndexTypeShouldWork.types

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ class Test<T extends A> {
2222

2323
this.attrs.params!.name;
2424
>this.attrs.params!.name : string
25-
>this.attrs.params! : { name: string; }
26-
>this.attrs.params : { name: string; } | undefined
25+
>this.attrs.params! : NonNullable<T["params"]>
26+
>this.attrs.params : T["params"]
2727
>this.attrs : Readonly<T>
2828
>this : this
2929
>attrs : Readonly<T>
30-
>params : { name: string; } | undefined
30+
>params : T["params"]
3131
>name : string
3232
}
3333
}
@@ -76,14 +76,14 @@ class Test2<T extends A> {
7676
>T : T
7777

7878
m() {
79-
>m : () => { name: string; }
79+
>m : () => NonNullable<T["params"]>
8080

8181
return this.attrs.params!; // Return type should maintain relationship with `T` after being not-null-asserted, ideally
82-
>this.attrs.params! : { name: string; }
83-
>this.attrs.params : { name: string; } | undefined
82+
>this.attrs.params! : NonNullable<T["params"]>
83+
>this.attrs.params : T["params"]
8484
>this.attrs : Readonly<T>
8585
>this : this
8686
>attrs : Readonly<T>
87-
>params : { name: string; } | undefined
87+
>params : T["params"]
8888
}
8989
}

0 commit comments

Comments
 (0)