Fixes to inference and mapped types in --strictOptionalProperties mode (#44595)

* Fix Required<T> and inference to index signatures in --strictOptionalProperties mode

* Add tests

* Accept new baselines
This commit is contained in:
Anders Hejlsberg
2021-06-15 14:16:38 -07:00
committed by GitHub
parent b74b8977d5
commit 6bb1f0792b
10 changed files with 659 additions and 11 deletions

View File

@@ -11181,7 +11181,7 @@ namespace ts {
// type, we include 'undefined' in the type. Similarly, when creating a non-optional property in strictNullChecks
// mode, if the underlying property is optional we remove 'undefined' from the type.
let type = strictNullChecks && symbol.flags & SymbolFlags.Optional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType, /*isProperty*/ true) :
symbol.checkFlags & CheckFlags.StripOptional ? getTypeWithFacts(propType, TypeFacts.NEUndefined) :
symbol.checkFlags & CheckFlags.StripOptional ? removeMissingOrUndefinedType(propType) :
propType;
if (!popTypeResolution()) {
error(currentNode, Diagnostics.Type_of_property_0_circularly_references_itself_in_mapped_type_1, symbolToString(symbol), typeToString(mappedType));
@@ -12045,7 +12045,7 @@ namespace ts {
for (const prop of getPropertiesOfType(type)) {
if (kind === IndexKind.String || isNumericLiteralName(prop.escapedName)) {
const propType = getTypeOfSymbol(prop);
propTypes.push(prop.flags & SymbolFlags.Optional ? getTypeWithFacts(propType, TypeFacts.NEUndefined) : propType);
propTypes.push(prop.flags & SymbolFlags.Optional ? removeMissingOrUndefinedType(propType) : propType);
}
}
if (kind === IndexKind.String) {
@@ -20331,12 +20331,8 @@ namespace ts {
return strictNullChecks ? getUnionType([type, optionalType]) : type;
}
function isNotOptionalTypeMarker(type: Type) {
return type !== optionalType;
}
function removeOptionalTypeMarker(type: Type): Type {
return strictNullChecks ? filterType(type, isNotOptionalTypeMarker) : type;
return strictNullChecks ? removeType(type, optionalType) : type;
}
function propagateOptionalTypeMarker(type: Type, node: OptionalChain, wasOptional: boolean) {
@@ -20350,13 +20346,17 @@ namespace ts {
}
function removeMissingType(type: Type, isOptional: boolean) {
return strictOptionalProperties && isOptional ? filterType(type, t => t !== missingType) : type;
return strictOptionalProperties && isOptional ? removeType(type, missingType) : type;
}
function containsMissingType(type: Type) {
return strictOptionalProperties && (type === missingType || type.flags & TypeFlags.Union && containsType((type as UnionType).types, missingType));
}
function removeMissingOrUndefinedType(type: Type): Type {
return strictOptionalProperties ? removeType(type, missingType) : getTypeWithFacts(type, TypeFacts.NEUndefined);
}
/**
* Is source potentially coercible to target type under `==`.
* Assumes that `source` is a constituent of a union, hence
@@ -22562,6 +22562,10 @@ namespace ts {
return type.flags & TypeFlags.Never || f(type) ? type : neverType;
}
function removeType(type: Type, targetType: Type) {
return filterType(type, t => t !== targetType);
}
function countTypes(type: Type) {
return type.flags & TypeFlags.Union ? (type as UnionType).types.length : 1;
}
@@ -23460,7 +23464,7 @@ namespace ts {
const candidate = getConstituentTypeForKeyType(type as UnionType, getTypeOfExpression(value));
if (candidate) {
return operator === (assumeTrue ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken) ? candidate :
isUnitType(getTypeOfPropertyOfType(candidate, keyPropertyName) || unknownType) ? filterType(type, t => t !== candidate) :
isUnitType(getTypeOfPropertyOfType(candidate, keyPropertyName) || unknownType) ? removeType(type, candidate) :
type;
}
}

View File

@@ -0,0 +1,108 @@
//// [inferenceOptionalProperties.ts]
declare function test<T>(x: { [key: string]: T }): T;
declare let x1: { a?: string, b?: number };
declare let x2: { a?: string, b?: number | undefined };
const y1 = test(x1);
const y2 = test(x2);
var v1: Required<{ a?: string, b?: number }>;
var v1: { a: string, b: number };
var v2: Required<{ a?: string, b?: number | undefined }>;
var v2: { a: string, b: number | undefined };
var v3: Partial<{ a: string, b: string }>;
var v3: { a?: string, b?: string };
var v4: Partial<{ a: string, b: string | undefined }>;
var v4: { a?: string, b?: string | undefined };
var v5: Required<Partial<{ a: string, b: string }>>;
var v5: { a: string, b: string };
var v6: Required<Partial<{ a: string, b: string | undefined }>>;
var v6: { a: string, b: string | undefined };
//// [inferenceOptionalProperties.js]
"use strict";
var y1 = test(x1);
var y2 = test(x2);
var v1;
var v1;
var v2;
var v2;
var v3;
var v3;
var v4;
var v4;
var v5;
var v5;
var v6;
var v6;
//// [inferenceOptionalProperties.d.ts]
declare function test<T>(x: {
[key: string]: T;
}): T;
declare let x1: {
a?: string;
b?: number;
};
declare let x2: {
a?: string;
b?: number | undefined;
};
declare const y1: string | number;
declare const y2: string | number | undefined;
declare var v1: Required<{
a?: string;
b?: number;
}>;
declare var v1: {
a: string;
b: number;
};
declare var v2: Required<{
a?: string;
b?: number | undefined;
}>;
declare var v2: {
a: string;
b: number | undefined;
};
declare var v3: Partial<{
a: string;
b: string;
}>;
declare var v3: {
a?: string;
b?: string;
};
declare var v4: Partial<{
a: string;
b: string | undefined;
}>;
declare var v4: {
a?: string;
b?: string | undefined;
};
declare var v5: Required<Partial<{
a: string;
b: string;
}>>;
declare var v5: {
a: string;
b: string;
};
declare var v6: Required<Partial<{
a: string;
b: string | undefined;
}>>;
declare var v6: {
a: string;
b: string | undefined;
};

View File

@@ -0,0 +1,97 @@
=== tests/cases/compiler/inferenceOptionalProperties.ts ===
declare function test<T>(x: { [key: string]: T }): T;
>test : Symbol(test, Decl(inferenceOptionalProperties.ts, 0, 0))
>T : Symbol(T, Decl(inferenceOptionalProperties.ts, 0, 22))
>x : Symbol(x, Decl(inferenceOptionalProperties.ts, 0, 25))
>key : Symbol(key, Decl(inferenceOptionalProperties.ts, 0, 31))
>T : Symbol(T, Decl(inferenceOptionalProperties.ts, 0, 22))
>T : Symbol(T, Decl(inferenceOptionalProperties.ts, 0, 22))
declare let x1: { a?: string, b?: number };
>x1 : Symbol(x1, Decl(inferenceOptionalProperties.ts, 2, 11))
>a : Symbol(a, Decl(inferenceOptionalProperties.ts, 2, 17))
>b : Symbol(b, Decl(inferenceOptionalProperties.ts, 2, 29))
declare let x2: { a?: string, b?: number | undefined };
>x2 : Symbol(x2, Decl(inferenceOptionalProperties.ts, 3, 11))
>a : Symbol(a, Decl(inferenceOptionalProperties.ts, 3, 17))
>b : Symbol(b, Decl(inferenceOptionalProperties.ts, 3, 29))
const y1 = test(x1);
>y1 : Symbol(y1, Decl(inferenceOptionalProperties.ts, 5, 5))
>test : Symbol(test, Decl(inferenceOptionalProperties.ts, 0, 0))
>x1 : Symbol(x1, Decl(inferenceOptionalProperties.ts, 2, 11))
const y2 = test(x2);
>y2 : Symbol(y2, Decl(inferenceOptionalProperties.ts, 6, 5))
>test : Symbol(test, Decl(inferenceOptionalProperties.ts, 0, 0))
>x2 : Symbol(x2, Decl(inferenceOptionalProperties.ts, 3, 11))
var v1: Required<{ a?: string, b?: number }>;
>v1 : Symbol(v1, Decl(inferenceOptionalProperties.ts, 8, 3), Decl(inferenceOptionalProperties.ts, 9, 3))
>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --))
>a : Symbol(a, Decl(inferenceOptionalProperties.ts, 8, 18))
>b : Symbol(b, Decl(inferenceOptionalProperties.ts, 8, 30))
var v1: { a: string, b: number };
>v1 : Symbol(v1, Decl(inferenceOptionalProperties.ts, 8, 3), Decl(inferenceOptionalProperties.ts, 9, 3))
>a : Symbol(a, Decl(inferenceOptionalProperties.ts, 9, 9))
>b : Symbol(b, Decl(inferenceOptionalProperties.ts, 9, 20))
var v2: Required<{ a?: string, b?: number | undefined }>;
>v2 : Symbol(v2, Decl(inferenceOptionalProperties.ts, 11, 3), Decl(inferenceOptionalProperties.ts, 12, 3))
>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --))
>a : Symbol(a, Decl(inferenceOptionalProperties.ts, 11, 18))
>b : Symbol(b, Decl(inferenceOptionalProperties.ts, 11, 30))
var v2: { a: string, b: number | undefined };
>v2 : Symbol(v2, Decl(inferenceOptionalProperties.ts, 11, 3), Decl(inferenceOptionalProperties.ts, 12, 3))
>a : Symbol(a, Decl(inferenceOptionalProperties.ts, 12, 9))
>b : Symbol(b, Decl(inferenceOptionalProperties.ts, 12, 20))
var v3: Partial<{ a: string, b: string }>;
>v3 : Symbol(v3, Decl(inferenceOptionalProperties.ts, 14, 3), Decl(inferenceOptionalProperties.ts, 15, 3))
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
>a : Symbol(a, Decl(inferenceOptionalProperties.ts, 14, 17))
>b : Symbol(b, Decl(inferenceOptionalProperties.ts, 14, 28))
var v3: { a?: string, b?: string };
>v3 : Symbol(v3, Decl(inferenceOptionalProperties.ts, 14, 3), Decl(inferenceOptionalProperties.ts, 15, 3))
>a : Symbol(a, Decl(inferenceOptionalProperties.ts, 15, 9))
>b : Symbol(b, Decl(inferenceOptionalProperties.ts, 15, 21))
var v4: Partial<{ a: string, b: string | undefined }>;
>v4 : Symbol(v4, Decl(inferenceOptionalProperties.ts, 17, 3), Decl(inferenceOptionalProperties.ts, 18, 3))
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
>a : Symbol(a, Decl(inferenceOptionalProperties.ts, 17, 17))
>b : Symbol(b, Decl(inferenceOptionalProperties.ts, 17, 28))
var v4: { a?: string, b?: string | undefined };
>v4 : Symbol(v4, Decl(inferenceOptionalProperties.ts, 17, 3), Decl(inferenceOptionalProperties.ts, 18, 3))
>a : Symbol(a, Decl(inferenceOptionalProperties.ts, 18, 9))
>b : Symbol(b, Decl(inferenceOptionalProperties.ts, 18, 21))
var v5: Required<Partial<{ a: string, b: string }>>;
>v5 : Symbol(v5, Decl(inferenceOptionalProperties.ts, 20, 3), Decl(inferenceOptionalProperties.ts, 21, 3))
>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --))
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
>a : Symbol(a, Decl(inferenceOptionalProperties.ts, 20, 26))
>b : Symbol(b, Decl(inferenceOptionalProperties.ts, 20, 37))
var v5: { a: string, b: string };
>v5 : Symbol(v5, Decl(inferenceOptionalProperties.ts, 20, 3), Decl(inferenceOptionalProperties.ts, 21, 3))
>a : Symbol(a, Decl(inferenceOptionalProperties.ts, 21, 9))
>b : Symbol(b, Decl(inferenceOptionalProperties.ts, 21, 20))
var v6: Required<Partial<{ a: string, b: string | undefined }>>;
>v6 : Symbol(v6, Decl(inferenceOptionalProperties.ts, 23, 3), Decl(inferenceOptionalProperties.ts, 24, 3))
>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --))
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
>a : Symbol(a, Decl(inferenceOptionalProperties.ts, 23, 26))
>b : Symbol(b, Decl(inferenceOptionalProperties.ts, 23, 37))
var v6: { a: string, b: string | undefined };
>v6 : Symbol(v6, Decl(inferenceOptionalProperties.ts, 23, 3), Decl(inferenceOptionalProperties.ts, 24, 3))
>a : Symbol(a, Decl(inferenceOptionalProperties.ts, 24, 9))
>b : Symbol(b, Decl(inferenceOptionalProperties.ts, 24, 20))

View File

@@ -0,0 +1,88 @@
=== tests/cases/compiler/inferenceOptionalProperties.ts ===
declare function test<T>(x: { [key: string]: T }): T;
>test : <T>(x: { [key: string]: T; }) => T
>x : { [key: string]: T; }
>key : string
declare let x1: { a?: string, b?: number };
>x1 : { a?: string; b?: number; }
>a : string | undefined
>b : number | undefined
declare let x2: { a?: string, b?: number | undefined };
>x2 : { a?: string; b?: number | undefined; }
>a : string | undefined
>b : number | undefined
const y1 = test(x1);
>y1 : string | number
>test(x1) : string | number
>test : <T>(x: { [key: string]: T; }) => T
>x1 : { a?: string; b?: number; }
const y2 = test(x2);
>y2 : string | number | undefined
>test(x2) : string | number | undefined
>test : <T>(x: { [key: string]: T; }) => T
>x2 : { a?: string; b?: number | undefined; }
var v1: Required<{ a?: string, b?: number }>;
>v1 : Required<{ a?: string; b?: number; }>
>a : string | undefined
>b : number | undefined
var v1: { a: string, b: number };
>v1 : Required<{ a?: string; b?: number; }>
>a : string
>b : number
var v2: Required<{ a?: string, b?: number | undefined }>;
>v2 : Required<{ a?: string; b?: number | undefined; }>
>a : string | undefined
>b : number | undefined
var v2: { a: string, b: number | undefined };
>v2 : Required<{ a?: string; b?: number | undefined; }>
>a : string
>b : number | undefined
var v3: Partial<{ a: string, b: string }>;
>v3 : Partial<{ a: string; b: string; }>
>a : string
>b : string
var v3: { a?: string, b?: string };
>v3 : Partial<{ a: string; b: string; }>
>a : string | undefined
>b : string | undefined
var v4: Partial<{ a: string, b: string | undefined }>;
>v4 : Partial<{ a: string; b: string | undefined; }>
>a : string
>b : string | undefined
var v4: { a?: string, b?: string | undefined };
>v4 : Partial<{ a: string; b: string | undefined; }>
>a : string | undefined
>b : string | undefined
var v5: Required<Partial<{ a: string, b: string }>>;
>v5 : Required<Partial<{ a: string; b: string; }>>
>a : string
>b : string
var v5: { a: string, b: string };
>v5 : Required<Partial<{ a: string; b: string; }>>
>a : string
>b : string
var v6: Required<Partial<{ a: string, b: string | undefined }>>;
>v6 : Required<Partial<{ a: string; b: string | undefined; }>>
>a : string
>b : string | undefined
var v6: { a: string, b: string | undefined };
>v6 : Required<Partial<{ a: string; b: string | undefined; }>>
>a : string
>b : string | undefined

View File

@@ -0,0 +1,108 @@
//// [inferenceOptionalPropertiesStrict.ts]
declare function test<T>(x: { [key: string]: T }): T;
declare let x1: { a?: string, b?: number };
declare let x2: { a?: string, b?: number | undefined };
const y1 = test(x1);
const y2 = test(x2);
var v1: Required<{ a?: string, b?: number }>;
var v1: { a: string, b: number };
var v2: Required<{ a?: string, b?: number | undefined }>;
var v2: { a: string, b: number | undefined };
var v3: Partial<{ a: string, b: string }>;
var v3: { a?: string, b?: string };
var v4: Partial<{ a: string, b: string | undefined }>;
var v4: { a?: string, b?: string | undefined };
var v5: Required<Partial<{ a: string, b: string }>>;
var v5: { a: string, b: string };
var v6: Required<Partial<{ a: string, b: string | undefined }>>;
var v6: { a: string, b: string | undefined };
//// [inferenceOptionalPropertiesStrict.js]
"use strict";
var y1 = test(x1);
var y2 = test(x2);
var v1;
var v1;
var v2;
var v2;
var v3;
var v3;
var v4;
var v4;
var v5;
var v5;
var v6;
var v6;
//// [inferenceOptionalPropertiesStrict.d.ts]
declare function test<T>(x: {
[key: string]: T;
}): T;
declare let x1: {
a?: string;
b?: number;
};
declare let x2: {
a?: string;
b?: number | undefined;
};
declare const y1: string | number;
declare const y2: string | number | undefined;
declare var v1: Required<{
a?: string;
b?: number;
}>;
declare var v1: {
a: string;
b: number;
};
declare var v2: Required<{
a?: string;
b?: number | undefined;
}>;
declare var v2: {
a: string;
b: number | undefined;
};
declare var v3: Partial<{
a: string;
b: string;
}>;
declare var v3: {
a?: string;
b?: string;
};
declare var v4: Partial<{
a: string;
b: string | undefined;
}>;
declare var v4: {
a?: string;
b?: string | undefined;
};
declare var v5: Required<Partial<{
a: string;
b: string;
}>>;
declare var v5: {
a: string;
b: string;
};
declare var v6: Required<Partial<{
a: string;
b: string | undefined;
}>>;
declare var v6: {
a: string;
b: string | undefined;
};

View File

@@ -0,0 +1,97 @@
=== tests/cases/compiler/inferenceOptionalPropertiesStrict.ts ===
declare function test<T>(x: { [key: string]: T }): T;
>test : Symbol(test, Decl(inferenceOptionalPropertiesStrict.ts, 0, 0))
>T : Symbol(T, Decl(inferenceOptionalPropertiesStrict.ts, 0, 22))
>x : Symbol(x, Decl(inferenceOptionalPropertiesStrict.ts, 0, 25))
>key : Symbol(key, Decl(inferenceOptionalPropertiesStrict.ts, 0, 31))
>T : Symbol(T, Decl(inferenceOptionalPropertiesStrict.ts, 0, 22))
>T : Symbol(T, Decl(inferenceOptionalPropertiesStrict.ts, 0, 22))
declare let x1: { a?: string, b?: number };
>x1 : Symbol(x1, Decl(inferenceOptionalPropertiesStrict.ts, 2, 11))
>a : Symbol(a, Decl(inferenceOptionalPropertiesStrict.ts, 2, 17))
>b : Symbol(b, Decl(inferenceOptionalPropertiesStrict.ts, 2, 29))
declare let x2: { a?: string, b?: number | undefined };
>x2 : Symbol(x2, Decl(inferenceOptionalPropertiesStrict.ts, 3, 11))
>a : Symbol(a, Decl(inferenceOptionalPropertiesStrict.ts, 3, 17))
>b : Symbol(b, Decl(inferenceOptionalPropertiesStrict.ts, 3, 29))
const y1 = test(x1);
>y1 : Symbol(y1, Decl(inferenceOptionalPropertiesStrict.ts, 5, 5))
>test : Symbol(test, Decl(inferenceOptionalPropertiesStrict.ts, 0, 0))
>x1 : Symbol(x1, Decl(inferenceOptionalPropertiesStrict.ts, 2, 11))
const y2 = test(x2);
>y2 : Symbol(y2, Decl(inferenceOptionalPropertiesStrict.ts, 6, 5))
>test : Symbol(test, Decl(inferenceOptionalPropertiesStrict.ts, 0, 0))
>x2 : Symbol(x2, Decl(inferenceOptionalPropertiesStrict.ts, 3, 11))
var v1: Required<{ a?: string, b?: number }>;
>v1 : Symbol(v1, Decl(inferenceOptionalPropertiesStrict.ts, 8, 3), Decl(inferenceOptionalPropertiesStrict.ts, 9, 3))
>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --))
>a : Symbol(a, Decl(inferenceOptionalPropertiesStrict.ts, 8, 18))
>b : Symbol(b, Decl(inferenceOptionalPropertiesStrict.ts, 8, 30))
var v1: { a: string, b: number };
>v1 : Symbol(v1, Decl(inferenceOptionalPropertiesStrict.ts, 8, 3), Decl(inferenceOptionalPropertiesStrict.ts, 9, 3))
>a : Symbol(a, Decl(inferenceOptionalPropertiesStrict.ts, 9, 9))
>b : Symbol(b, Decl(inferenceOptionalPropertiesStrict.ts, 9, 20))
var v2: Required<{ a?: string, b?: number | undefined }>;
>v2 : Symbol(v2, Decl(inferenceOptionalPropertiesStrict.ts, 11, 3), Decl(inferenceOptionalPropertiesStrict.ts, 12, 3))
>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --))
>a : Symbol(a, Decl(inferenceOptionalPropertiesStrict.ts, 11, 18))
>b : Symbol(b, Decl(inferenceOptionalPropertiesStrict.ts, 11, 30))
var v2: { a: string, b: number | undefined };
>v2 : Symbol(v2, Decl(inferenceOptionalPropertiesStrict.ts, 11, 3), Decl(inferenceOptionalPropertiesStrict.ts, 12, 3))
>a : Symbol(a, Decl(inferenceOptionalPropertiesStrict.ts, 12, 9))
>b : Symbol(b, Decl(inferenceOptionalPropertiesStrict.ts, 12, 20))
var v3: Partial<{ a: string, b: string }>;
>v3 : Symbol(v3, Decl(inferenceOptionalPropertiesStrict.ts, 14, 3), Decl(inferenceOptionalPropertiesStrict.ts, 15, 3))
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
>a : Symbol(a, Decl(inferenceOptionalPropertiesStrict.ts, 14, 17))
>b : Symbol(b, Decl(inferenceOptionalPropertiesStrict.ts, 14, 28))
var v3: { a?: string, b?: string };
>v3 : Symbol(v3, Decl(inferenceOptionalPropertiesStrict.ts, 14, 3), Decl(inferenceOptionalPropertiesStrict.ts, 15, 3))
>a : Symbol(a, Decl(inferenceOptionalPropertiesStrict.ts, 15, 9))
>b : Symbol(b, Decl(inferenceOptionalPropertiesStrict.ts, 15, 21))
var v4: Partial<{ a: string, b: string | undefined }>;
>v4 : Symbol(v4, Decl(inferenceOptionalPropertiesStrict.ts, 17, 3), Decl(inferenceOptionalPropertiesStrict.ts, 18, 3))
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
>a : Symbol(a, Decl(inferenceOptionalPropertiesStrict.ts, 17, 17))
>b : Symbol(b, Decl(inferenceOptionalPropertiesStrict.ts, 17, 28))
var v4: { a?: string, b?: string | undefined };
>v4 : Symbol(v4, Decl(inferenceOptionalPropertiesStrict.ts, 17, 3), Decl(inferenceOptionalPropertiesStrict.ts, 18, 3))
>a : Symbol(a, Decl(inferenceOptionalPropertiesStrict.ts, 18, 9))
>b : Symbol(b, Decl(inferenceOptionalPropertiesStrict.ts, 18, 21))
var v5: Required<Partial<{ a: string, b: string }>>;
>v5 : Symbol(v5, Decl(inferenceOptionalPropertiesStrict.ts, 20, 3), Decl(inferenceOptionalPropertiesStrict.ts, 21, 3))
>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --))
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
>a : Symbol(a, Decl(inferenceOptionalPropertiesStrict.ts, 20, 26))
>b : Symbol(b, Decl(inferenceOptionalPropertiesStrict.ts, 20, 37))
var v5: { a: string, b: string };
>v5 : Symbol(v5, Decl(inferenceOptionalPropertiesStrict.ts, 20, 3), Decl(inferenceOptionalPropertiesStrict.ts, 21, 3))
>a : Symbol(a, Decl(inferenceOptionalPropertiesStrict.ts, 21, 9))
>b : Symbol(b, Decl(inferenceOptionalPropertiesStrict.ts, 21, 20))
var v6: Required<Partial<{ a: string, b: string | undefined }>>;
>v6 : Symbol(v6, Decl(inferenceOptionalPropertiesStrict.ts, 23, 3), Decl(inferenceOptionalPropertiesStrict.ts, 24, 3))
>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --))
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
>a : Symbol(a, Decl(inferenceOptionalPropertiesStrict.ts, 23, 26))
>b : Symbol(b, Decl(inferenceOptionalPropertiesStrict.ts, 23, 37))
var v6: { a: string, b: string | undefined };
>v6 : Symbol(v6, Decl(inferenceOptionalPropertiesStrict.ts, 23, 3), Decl(inferenceOptionalPropertiesStrict.ts, 24, 3))
>a : Symbol(a, Decl(inferenceOptionalPropertiesStrict.ts, 24, 9))
>b : Symbol(b, Decl(inferenceOptionalPropertiesStrict.ts, 24, 20))

View File

@@ -0,0 +1,88 @@
=== tests/cases/compiler/inferenceOptionalPropertiesStrict.ts ===
declare function test<T>(x: { [key: string]: T }): T;
>test : <T>(x: { [key: string]: T; }) => T
>x : { [key: string]: T; }
>key : string
declare let x1: { a?: string, b?: number };
>x1 : { a?: string; b?: number; }
>a : string | undefined
>b : number | undefined
declare let x2: { a?: string, b?: number | undefined };
>x2 : { a?: string; b?: number | undefined; }
>a : string | undefined
>b : number | undefined
const y1 = test(x1);
>y1 : string | number
>test(x1) : string | number
>test : <T>(x: { [key: string]: T; }) => T
>x1 : { a?: string; b?: number; }
const y2 = test(x2);
>y2 : string | number | undefined
>test(x2) : string | number | undefined
>test : <T>(x: { [key: string]: T; }) => T
>x2 : { a?: string; b?: number | undefined; }
var v1: Required<{ a?: string, b?: number }>;
>v1 : Required<{ a?: string; b?: number; }>
>a : string | undefined
>b : number | undefined
var v1: { a: string, b: number };
>v1 : Required<{ a?: string; b?: number; }>
>a : string
>b : number
var v2: Required<{ a?: string, b?: number | undefined }>;
>v2 : Required<{ a?: string; b?: number | undefined; }>
>a : string | undefined
>b : number | undefined
var v2: { a: string, b: number | undefined };
>v2 : Required<{ a?: string; b?: number | undefined; }>
>a : string
>b : number | undefined
var v3: Partial<{ a: string, b: string }>;
>v3 : Partial<{ a: string; b: string; }>
>a : string
>b : string
var v3: { a?: string, b?: string };
>v3 : Partial<{ a: string; b: string; }>
>a : string | undefined
>b : string | undefined
var v4: Partial<{ a: string, b: string | undefined }>;
>v4 : Partial<{ a: string; b: string | undefined; }>
>a : string
>b : string | undefined
var v4: { a?: string, b?: string | undefined };
>v4 : Partial<{ a: string; b: string | undefined; }>
>a : string | undefined
>b : string | undefined
var v5: Required<Partial<{ a: string, b: string }>>;
>v5 : Required<Partial<{ a: string; b: string; }>>
>a : string
>b : string
var v5: { a: string, b: string };
>v5 : Required<Partial<{ a: string; b: string; }>>
>a : string
>b : string
var v6: Required<Partial<{ a: string, b: string | undefined }>>;
>v6 : Required<Partial<{ a: string; b: string | undefined; }>>
>a : string
>b : string | undefined
var v6: { a: string, b: string | undefined };
>v6 : Required<Partial<{ a: string; b: string | undefined; }>>
>a : string
>b : string | undefined

View File

@@ -43,8 +43,8 @@ let a3 = foo(x3); // string | number
>x3 : { a: string; b?: number; }
let a4 = foo(x4); // string | number
>a4 : string | number
>foo(x4) : string | number
>a4 : string | number | undefined
>foo(x4) : string | number | undefined
>foo : <T>(obj: { [x: string]: T; }) => T
>x4 : { a: string; b?: number | undefined; }

View File

@@ -0,0 +1,29 @@
// @strict: true
// @strictOptionalProperties: true
// @declaration: true
declare function test<T>(x: { [key: string]: T }): T;
declare let x1: { a?: string, b?: number };
declare let x2: { a?: string, b?: number | undefined };
const y1 = test(x1);
const y2 = test(x2);
var v1: Required<{ a?: string, b?: number }>;
var v1: { a: string, b: number };
var v2: Required<{ a?: string, b?: number | undefined }>;
var v2: { a: string, b: number | undefined };
var v3: Partial<{ a: string, b: string }>;
var v3: { a?: string, b?: string };
var v4: Partial<{ a: string, b: string | undefined }>;
var v4: { a?: string, b?: string | undefined };
var v5: Required<Partial<{ a: string, b: string }>>;
var v5: { a: string, b: string };
var v6: Required<Partial<{ a: string, b: string | undefined }>>;
var v6: { a: string, b: string | undefined };

View File

@@ -0,0 +1,29 @@
// @strict: true
// @strictOptionalProperties: true
// @declaration: true
declare function test<T>(x: { [key: string]: T }): T;
declare let x1: { a?: string, b?: number };
declare let x2: { a?: string, b?: number | undefined };
const y1 = test(x1);
const y2 = test(x2);
var v1: Required<{ a?: string, b?: number }>;
var v1: { a: string, b: number };
var v2: Required<{ a?: string, b?: number | undefined }>;
var v2: { a: string, b: number | undefined };
var v3: Partial<{ a: string, b: string }>;
var v3: { a?: string, b?: string };
var v4: Partial<{ a: string, b: string | undefined }>;
var v4: { a?: string, b?: string | undefined };
var v5: Required<Partial<{ a: string, b: string }>>;
var v5: { a: string, b: string };
var v6: Required<Partial<{ a: string, b: string | undefined }>>;
var v6: { a: string, b: string | undefined };