mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-10 15:25:54 -06:00
Ensure singleton types always compare identical (#44565)
* Singleton types should compare identical + fix boolean types * Add tests * Accept new baselines
This commit is contained in:
parent
4829a7fedd
commit
6a1623d413
@ -757,12 +757,7 @@ namespace ts {
|
||||
falseType.freshType = falseType;
|
||||
regularFalseType.regularType = regularFalseType;
|
||||
regularFalseType.freshType = falseType;
|
||||
const booleanType = createBooleanType([regularFalseType, regularTrueType]);
|
||||
// Also mark all combinations of fresh/regular booleans as "Boolean" so they print as `boolean` instead of `true | false`
|
||||
// (The union is cached, so simply doing the marking here is sufficient)
|
||||
createBooleanType([regularFalseType, trueType]);
|
||||
createBooleanType([falseType, regularTrueType]);
|
||||
createBooleanType([falseType, trueType]);
|
||||
const booleanType = getUnionType([regularFalseType, regularTrueType]);
|
||||
const esSymbolType = createIntrinsicType(TypeFlags.ESSymbol, "symbol");
|
||||
const voidType = createIntrinsicType(TypeFlags.Void, "void");
|
||||
const neverType = createIntrinsicType(TypeFlags.Never, "never");
|
||||
@ -3837,13 +3832,6 @@ namespace ts {
|
||||
return type;
|
||||
}
|
||||
|
||||
function createBooleanType(trueFalseTypes: readonly Type[]): IntrinsicType & UnionType {
|
||||
const type = getUnionType(trueFalseTypes) as IntrinsicType & UnionType;
|
||||
type.flags |= TypeFlags.Boolean;
|
||||
type.intrinsicName = "boolean";
|
||||
return type;
|
||||
}
|
||||
|
||||
function createObjectType(objectFlags: ObjectFlags, symbol?: Symbol): ObjectType {
|
||||
const type = createType(TypeFlags.Object) as ObjectType;
|
||||
type.objectFlags = objectFlags;
|
||||
@ -4584,7 +4572,7 @@ namespace ts {
|
||||
context.approximateLength += 6;
|
||||
return factory.createKeywordTypeNode(SyntaxKind.BigIntKeyword);
|
||||
}
|
||||
if (type.flags & TypeFlags.Boolean) {
|
||||
if (type.flags & TypeFlags.Boolean && !type.aliasSymbol) {
|
||||
context.approximateLength += 7;
|
||||
return factory.createKeywordTypeNode(SyntaxKind.BooleanKeyword);
|
||||
}
|
||||
@ -13975,16 +13963,6 @@ namespace ts {
|
||||
return a.kind === b.kind && a.parameterIndex === b.parameterIndex;
|
||||
}
|
||||
|
||||
function createUnionType(types: Type[], aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[], origin?: Type) {
|
||||
const result = createType(TypeFlags.Union) as UnionType;
|
||||
result.objectFlags = getPropagatingFlagsOfTypes(types, /*excludeKinds*/ TypeFlags.Nullable);
|
||||
result.types = types;
|
||||
result.origin = origin;
|
||||
result.aliasSymbol = aliasSymbol;
|
||||
result.aliasTypeArguments = aliasTypeArguments;
|
||||
return result;
|
||||
}
|
||||
|
||||
// This function assumes the constituent type list is sorted and deduplicated.
|
||||
function getUnionTypeFromSortedList(types: Type[], objectFlags: ObjectFlags, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[], origin?: Type): Type {
|
||||
if (types.length === 0) {
|
||||
@ -14000,8 +13978,16 @@ namespace ts {
|
||||
const id = typeKey + getAliasId(aliasSymbol, aliasTypeArguments);
|
||||
let type = unionTypes.get(id);
|
||||
if (!type) {
|
||||
type = createUnionType(types, aliasSymbol, aliasTypeArguments, origin);
|
||||
type.objectFlags |= objectFlags;
|
||||
type = createType(TypeFlags.Union) as UnionType;
|
||||
type.objectFlags = objectFlags | getPropagatingFlagsOfTypes(types, /*excludeKinds*/ TypeFlags.Nullable);
|
||||
type.types = types;
|
||||
type.origin = origin;
|
||||
type.aliasSymbol = aliasSymbol;
|
||||
type.aliasTypeArguments = aliasTypeArguments;
|
||||
if (types.length === 2 && types[0].flags & TypeFlags.BooleanLiteral && types[1].flags & TypeFlags.BooleanLiteral) {
|
||||
type.flags |= TypeFlags.Boolean;
|
||||
(type as UnionType & IntrinsicType).intrinsicName = "boolean";
|
||||
}
|
||||
unionTypes.set(id, type);
|
||||
}
|
||||
return type;
|
||||
@ -17329,8 +17315,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!(source.flags & TypeFlags.UnionOrIntersection) && !(target.flags & TypeFlags.UnionOrIntersection) &&
|
||||
source.flags !== target.flags && !(source.flags & TypeFlags.Substructure)) return false;
|
||||
if (source.flags !== target.flags) return false;
|
||||
if (source.flags & TypeFlags.Singleton) return true;
|
||||
}
|
||||
if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Object) {
|
||||
const related = relation.get(getRelationKey(source, target, IntersectionState.None, relation));
|
||||
@ -17932,12 +17918,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isIdenticalTo(source: Type, target: Type): Ternary {
|
||||
const flags = source.flags & target.flags;
|
||||
if (!(flags & TypeFlags.Substructure)) {
|
||||
return Ternary.False;
|
||||
}
|
||||
if (source.flags !== target.flags) return Ternary.False;
|
||||
if (source.flags & TypeFlags.Singleton) return Ternary.True;
|
||||
traceUnionsOrIntersectionsTooLarge(source, target);
|
||||
if (flags & TypeFlags.UnionOrIntersection) {
|
||||
if (source.flags & TypeFlags.UnionOrIntersection) {
|
||||
let result = eachTypeRelatedToSomeType(source as UnionOrIntersectionType, target as UnionOrIntersectionType);
|
||||
if (result) {
|
||||
result &= eachTypeRelatedToSomeType(target as UnionOrIntersectionType, source as UnionOrIntersectionType);
|
||||
@ -21132,7 +21116,6 @@ namespace ts {
|
||||
inferFromTypes(originalSource, originalTarget);
|
||||
|
||||
function inferFromTypes(source: Type, target: Type): void {
|
||||
|
||||
if (!couldContainTypeVariables(target)) {
|
||||
return;
|
||||
}
|
||||
@ -21750,7 +21733,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isTypeOrBaseIdenticalTo(s: Type, t: Type) {
|
||||
return isTypeIdenticalTo(s, t) || !!(t.flags & TypeFlags.String && s.flags & TypeFlags.StringLiteral || t.flags & TypeFlags.Number && s.flags & TypeFlags.NumberLiteral);
|
||||
return strictOptionalProperties && t === missingType ? s === t :
|
||||
(isTypeIdenticalTo(s, t) || !!(t.flags & TypeFlags.String && s.flags & TypeFlags.StringLiteral || t.flags & TypeFlags.Number && s.flags & TypeFlags.NumberLiteral));
|
||||
}
|
||||
|
||||
function isTypeCloselyMatchedBy(s: Type, t: Type) {
|
||||
|
||||
@ -5090,7 +5090,7 @@ namespace ts {
|
||||
/* @internal */
|
||||
Simplifiable = IndexedAccess | Conditional,
|
||||
/* @internal */
|
||||
Substructure = Object | Union | Intersection | Index | IndexedAccess | Conditional | Substitution | TemplateLiteral | StringMapping,
|
||||
Singleton = Any | Unknown | String | Number | Boolean | BigInt | ESSymbol | Void | Undefined | Null | Never | NonPrimitive,
|
||||
// 'Narrowable' types are types where narrowing actually narrows.
|
||||
// This *should* be every type other than null, undefined, void, and never
|
||||
Narrowable = Any | Unknown | StructuredOrInstantiable | StringLike | NumberLike | BigIntLike | BooleanLike | ESSymbol | UniqueESSymbol | NonPrimitive,
|
||||
|
||||
@ -182,4 +182,64 @@ tests/cases/compiler/strictOptionalProperties1.ts(119,5): error TS2411: Property
|
||||
~~~
|
||||
!!! error TS2411: Property 'bar' of type 'string | undefined' is not assignable to string index type 'string'.
|
||||
}
|
||||
|
||||
// Strict optional properties and inference
|
||||
|
||||
declare let ox1: { p: string };
|
||||
declare let ox2: { p: string | undefined };
|
||||
declare let ox3: { p?: string };
|
||||
declare let ox4: { p?: string | undefined };
|
||||
|
||||
declare let tx1: [string];
|
||||
declare let tx2: [string | undefined];
|
||||
declare let tx3: [string?];
|
||||
declare let tx4: [(string | undefined)?];
|
||||
|
||||
declare function f11<T>(x: { p?: T }): T;
|
||||
|
||||
f11(ox1); // string
|
||||
f11(ox2); // string | undefined
|
||||
f11(ox3); // string
|
||||
f11(ox4); // string | undefined
|
||||
|
||||
declare function f12<T>(x: [T?]): T;
|
||||
|
||||
f12(tx1); // string
|
||||
f12(tx2); // string | undefined
|
||||
f12(tx3); // string
|
||||
f12(tx4); // string | undefined
|
||||
|
||||
declare function f13<T>(x: Partial<T>): T;
|
||||
|
||||
f13(ox1); // { p: string }
|
||||
f13(ox2); // { p: string | undefined }
|
||||
f13(ox3); // { p: string }
|
||||
f13(ox4); // { p: string | undefined }
|
||||
|
||||
f13(tx1); // [string]
|
||||
f13(tx2); // [string | undefined]
|
||||
f13(tx3); // [string]
|
||||
f13(tx4); // [string | undefined]
|
||||
|
||||
// Repro from #44388
|
||||
|
||||
type Undefinable<T> = T | undefined;
|
||||
|
||||
function expectNotUndefined<T>(value: Undefinable<T>): T {
|
||||
if (value === undefined) {
|
||||
throw new TypeError('value is undefined');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
interface Bar {
|
||||
bar?: number;
|
||||
}
|
||||
|
||||
function aa(input: Bar): void {
|
||||
const notUndefinedVal = expectNotUndefined(input.bar);
|
||||
bb(notUndefinedVal);
|
||||
}
|
||||
|
||||
declare function bb(input: number): void;
|
||||
|
||||
@ -119,6 +119,66 @@ interface Test {
|
||||
foo?: string; // Should be ok
|
||||
bar?: string | undefined; // Error
|
||||
}
|
||||
|
||||
// Strict optional properties and inference
|
||||
|
||||
declare let ox1: { p: string };
|
||||
declare let ox2: { p: string | undefined };
|
||||
declare let ox3: { p?: string };
|
||||
declare let ox4: { p?: string | undefined };
|
||||
|
||||
declare let tx1: [string];
|
||||
declare let tx2: [string | undefined];
|
||||
declare let tx3: [string?];
|
||||
declare let tx4: [(string | undefined)?];
|
||||
|
||||
declare function f11<T>(x: { p?: T }): T;
|
||||
|
||||
f11(ox1); // string
|
||||
f11(ox2); // string | undefined
|
||||
f11(ox3); // string
|
||||
f11(ox4); // string | undefined
|
||||
|
||||
declare function f12<T>(x: [T?]): T;
|
||||
|
||||
f12(tx1); // string
|
||||
f12(tx2); // string | undefined
|
||||
f12(tx3); // string
|
||||
f12(tx4); // string | undefined
|
||||
|
||||
declare function f13<T>(x: Partial<T>): T;
|
||||
|
||||
f13(ox1); // { p: string }
|
||||
f13(ox2); // { p: string | undefined }
|
||||
f13(ox3); // { p: string }
|
||||
f13(ox4); // { p: string | undefined }
|
||||
|
||||
f13(tx1); // [string]
|
||||
f13(tx2); // [string | undefined]
|
||||
f13(tx3); // [string]
|
||||
f13(tx4); // [string | undefined]
|
||||
|
||||
// Repro from #44388
|
||||
|
||||
type Undefinable<T> = T | undefined;
|
||||
|
||||
function expectNotUndefined<T>(value: Undefinable<T>): T {
|
||||
if (value === undefined) {
|
||||
throw new TypeError('value is undefined');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
interface Bar {
|
||||
bar?: number;
|
||||
}
|
||||
|
||||
function aa(input: Bar): void {
|
||||
const notUndefinedVal = expectNotUndefined(input.bar);
|
||||
bb(notUndefinedVal);
|
||||
}
|
||||
|
||||
declare function bb(input: number): void;
|
||||
|
||||
|
||||
//// [strictOptionalProperties1.js]
|
||||
@ -223,6 +283,32 @@ var t4 = [1, undefined, undefined];
|
||||
// Example from #13195
|
||||
var x = { foo: undefined };
|
||||
var y = __assign({ foo: 123 }, x);
|
||||
f11(ox1); // string
|
||||
f11(ox2); // string | undefined
|
||||
f11(ox3); // string
|
||||
f11(ox4); // string | undefined
|
||||
f12(tx1); // string
|
||||
f12(tx2); // string | undefined
|
||||
f12(tx3); // string
|
||||
f12(tx4); // string | undefined
|
||||
f13(ox1); // { p: string }
|
||||
f13(ox2); // { p: string | undefined }
|
||||
f13(ox3); // { p: string }
|
||||
f13(ox4); // { p: string | undefined }
|
||||
f13(tx1); // [string]
|
||||
f13(tx2); // [string | undefined]
|
||||
f13(tx3); // [string]
|
||||
f13(tx4); // [string | undefined]
|
||||
function expectNotUndefined(value) {
|
||||
if (value === undefined) {
|
||||
throw new TypeError('value is undefined');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
function aa(input) {
|
||||
var notUndefinedVal = expectNotUndefined(input.bar);
|
||||
bb(notUndefinedVal);
|
||||
}
|
||||
|
||||
|
||||
//// [strictOptionalProperties1.d.ts]
|
||||
@ -268,3 +354,31 @@ interface Test {
|
||||
foo?: string;
|
||||
bar?: string | undefined;
|
||||
}
|
||||
declare let ox1: {
|
||||
p: string;
|
||||
};
|
||||
declare let ox2: {
|
||||
p: string | undefined;
|
||||
};
|
||||
declare let ox3: {
|
||||
p?: string;
|
||||
};
|
||||
declare let ox4: {
|
||||
p?: string | undefined;
|
||||
};
|
||||
declare let tx1: [string];
|
||||
declare let tx2: [string | undefined];
|
||||
declare let tx3: [string?];
|
||||
declare let tx4: [(string | undefined)?];
|
||||
declare function f11<T>(x: {
|
||||
p?: T;
|
||||
}): T;
|
||||
declare function f12<T>(x: [T?]): T;
|
||||
declare function f13<T>(x: Partial<T>): T;
|
||||
declare type Undefinable<T> = T | undefined;
|
||||
declare function expectNotUndefined<T>(value: Undefinable<T>): T;
|
||||
interface Bar {
|
||||
bar?: number;
|
||||
}
|
||||
declare function aa(input: Bar): void;
|
||||
declare function bb(input: number): void;
|
||||
|
||||
@ -400,3 +400,174 @@ interface Test {
|
||||
>bar : Symbol(Test.bar, Decl(strictOptionalProperties1.ts, 117, 17))
|
||||
}
|
||||
|
||||
// Strict optional properties and inference
|
||||
|
||||
declare let ox1: { p: string };
|
||||
>ox1 : Symbol(ox1, Decl(strictOptionalProperties1.ts, 123, 11))
|
||||
>p : Symbol(p, Decl(strictOptionalProperties1.ts, 123, 18))
|
||||
|
||||
declare let ox2: { p: string | undefined };
|
||||
>ox2 : Symbol(ox2, Decl(strictOptionalProperties1.ts, 124, 11))
|
||||
>p : Symbol(p, Decl(strictOptionalProperties1.ts, 124, 18))
|
||||
|
||||
declare let ox3: { p?: string };
|
||||
>ox3 : Symbol(ox3, Decl(strictOptionalProperties1.ts, 125, 11))
|
||||
>p : Symbol(p, Decl(strictOptionalProperties1.ts, 125, 18))
|
||||
|
||||
declare let ox4: { p?: string | undefined };
|
||||
>ox4 : Symbol(ox4, Decl(strictOptionalProperties1.ts, 126, 11))
|
||||
>p : Symbol(p, Decl(strictOptionalProperties1.ts, 126, 18))
|
||||
|
||||
declare let tx1: [string];
|
||||
>tx1 : Symbol(tx1, Decl(strictOptionalProperties1.ts, 128, 11))
|
||||
|
||||
declare let tx2: [string | undefined];
|
||||
>tx2 : Symbol(tx2, Decl(strictOptionalProperties1.ts, 129, 11))
|
||||
|
||||
declare let tx3: [string?];
|
||||
>tx3 : Symbol(tx3, Decl(strictOptionalProperties1.ts, 130, 11))
|
||||
|
||||
declare let tx4: [(string | undefined)?];
|
||||
>tx4 : Symbol(tx4, Decl(strictOptionalProperties1.ts, 131, 11))
|
||||
|
||||
declare function f11<T>(x: { p?: T }): T;
|
||||
>f11 : Symbol(f11, Decl(strictOptionalProperties1.ts, 131, 41))
|
||||
>T : Symbol(T, Decl(strictOptionalProperties1.ts, 133, 21))
|
||||
>x : Symbol(x, Decl(strictOptionalProperties1.ts, 133, 24))
|
||||
>p : Symbol(p, Decl(strictOptionalProperties1.ts, 133, 28))
|
||||
>T : Symbol(T, Decl(strictOptionalProperties1.ts, 133, 21))
|
||||
>T : Symbol(T, Decl(strictOptionalProperties1.ts, 133, 21))
|
||||
|
||||
f11(ox1); // string
|
||||
>f11 : Symbol(f11, Decl(strictOptionalProperties1.ts, 131, 41))
|
||||
>ox1 : Symbol(ox1, Decl(strictOptionalProperties1.ts, 123, 11))
|
||||
|
||||
f11(ox2); // string | undefined
|
||||
>f11 : Symbol(f11, Decl(strictOptionalProperties1.ts, 131, 41))
|
||||
>ox2 : Symbol(ox2, Decl(strictOptionalProperties1.ts, 124, 11))
|
||||
|
||||
f11(ox3); // string
|
||||
>f11 : Symbol(f11, Decl(strictOptionalProperties1.ts, 131, 41))
|
||||
>ox3 : Symbol(ox3, Decl(strictOptionalProperties1.ts, 125, 11))
|
||||
|
||||
f11(ox4); // string | undefined
|
||||
>f11 : Symbol(f11, Decl(strictOptionalProperties1.ts, 131, 41))
|
||||
>ox4 : Symbol(ox4, Decl(strictOptionalProperties1.ts, 126, 11))
|
||||
|
||||
declare function f12<T>(x: [T?]): T;
|
||||
>f12 : Symbol(f12, Decl(strictOptionalProperties1.ts, 138, 9))
|
||||
>T : Symbol(T, Decl(strictOptionalProperties1.ts, 140, 21))
|
||||
>x : Symbol(x, Decl(strictOptionalProperties1.ts, 140, 24))
|
||||
>T : Symbol(T, Decl(strictOptionalProperties1.ts, 140, 21))
|
||||
>T : Symbol(T, Decl(strictOptionalProperties1.ts, 140, 21))
|
||||
|
||||
f12(tx1); // string
|
||||
>f12 : Symbol(f12, Decl(strictOptionalProperties1.ts, 138, 9))
|
||||
>tx1 : Symbol(tx1, Decl(strictOptionalProperties1.ts, 128, 11))
|
||||
|
||||
f12(tx2); // string | undefined
|
||||
>f12 : Symbol(f12, Decl(strictOptionalProperties1.ts, 138, 9))
|
||||
>tx2 : Symbol(tx2, Decl(strictOptionalProperties1.ts, 129, 11))
|
||||
|
||||
f12(tx3); // string
|
||||
>f12 : Symbol(f12, Decl(strictOptionalProperties1.ts, 138, 9))
|
||||
>tx3 : Symbol(tx3, Decl(strictOptionalProperties1.ts, 130, 11))
|
||||
|
||||
f12(tx4); // string | undefined
|
||||
>f12 : Symbol(f12, Decl(strictOptionalProperties1.ts, 138, 9))
|
||||
>tx4 : Symbol(tx4, Decl(strictOptionalProperties1.ts, 131, 11))
|
||||
|
||||
declare function f13<T>(x: Partial<T>): T;
|
||||
>f13 : Symbol(f13, Decl(strictOptionalProperties1.ts, 145, 9))
|
||||
>T : Symbol(T, Decl(strictOptionalProperties1.ts, 147, 21))
|
||||
>x : Symbol(x, Decl(strictOptionalProperties1.ts, 147, 24))
|
||||
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(strictOptionalProperties1.ts, 147, 21))
|
||||
>T : Symbol(T, Decl(strictOptionalProperties1.ts, 147, 21))
|
||||
|
||||
f13(ox1); // { p: string }
|
||||
>f13 : Symbol(f13, Decl(strictOptionalProperties1.ts, 145, 9))
|
||||
>ox1 : Symbol(ox1, Decl(strictOptionalProperties1.ts, 123, 11))
|
||||
|
||||
f13(ox2); // { p: string | undefined }
|
||||
>f13 : Symbol(f13, Decl(strictOptionalProperties1.ts, 145, 9))
|
||||
>ox2 : Symbol(ox2, Decl(strictOptionalProperties1.ts, 124, 11))
|
||||
|
||||
f13(ox3); // { p: string }
|
||||
>f13 : Symbol(f13, Decl(strictOptionalProperties1.ts, 145, 9))
|
||||
>ox3 : Symbol(ox3, Decl(strictOptionalProperties1.ts, 125, 11))
|
||||
|
||||
f13(ox4); // { p: string | undefined }
|
||||
>f13 : Symbol(f13, Decl(strictOptionalProperties1.ts, 145, 9))
|
||||
>ox4 : Symbol(ox4, Decl(strictOptionalProperties1.ts, 126, 11))
|
||||
|
||||
f13(tx1); // [string]
|
||||
>f13 : Symbol(f13, Decl(strictOptionalProperties1.ts, 145, 9))
|
||||
>tx1 : Symbol(tx1, Decl(strictOptionalProperties1.ts, 128, 11))
|
||||
|
||||
f13(tx2); // [string | undefined]
|
||||
>f13 : Symbol(f13, Decl(strictOptionalProperties1.ts, 145, 9))
|
||||
>tx2 : Symbol(tx2, Decl(strictOptionalProperties1.ts, 129, 11))
|
||||
|
||||
f13(tx3); // [string]
|
||||
>f13 : Symbol(f13, Decl(strictOptionalProperties1.ts, 145, 9))
|
||||
>tx3 : Symbol(tx3, Decl(strictOptionalProperties1.ts, 130, 11))
|
||||
|
||||
f13(tx4); // [string | undefined]
|
||||
>f13 : Symbol(f13, Decl(strictOptionalProperties1.ts, 145, 9))
|
||||
>tx4 : Symbol(tx4, Decl(strictOptionalProperties1.ts, 131, 11))
|
||||
|
||||
// Repro from #44388
|
||||
|
||||
type Undefinable<T> = T | undefined;
|
||||
>Undefinable : Symbol(Undefinable, Decl(strictOptionalProperties1.ts, 157, 9))
|
||||
>T : Symbol(T, Decl(strictOptionalProperties1.ts, 161, 17))
|
||||
>T : Symbol(T, Decl(strictOptionalProperties1.ts, 161, 17))
|
||||
|
||||
function expectNotUndefined<T>(value: Undefinable<T>): T {
|
||||
>expectNotUndefined : Symbol(expectNotUndefined, Decl(strictOptionalProperties1.ts, 161, 36))
|
||||
>T : Symbol(T, Decl(strictOptionalProperties1.ts, 163, 28))
|
||||
>value : Symbol(value, Decl(strictOptionalProperties1.ts, 163, 31))
|
||||
>Undefinable : Symbol(Undefinable, Decl(strictOptionalProperties1.ts, 157, 9))
|
||||
>T : Symbol(T, Decl(strictOptionalProperties1.ts, 163, 28))
|
||||
>T : Symbol(T, Decl(strictOptionalProperties1.ts, 163, 28))
|
||||
|
||||
if (value === undefined) {
|
||||
>value : Symbol(value, Decl(strictOptionalProperties1.ts, 163, 31))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
throw new TypeError('value is undefined');
|
||||
>TypeError : Symbol(TypeError, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
}
|
||||
return value;
|
||||
>value : Symbol(value, Decl(strictOptionalProperties1.ts, 163, 31))
|
||||
}
|
||||
|
||||
interface Bar {
|
||||
>Bar : Symbol(Bar, Decl(strictOptionalProperties1.ts, 168, 1))
|
||||
|
||||
bar?: number;
|
||||
>bar : Symbol(Bar.bar, Decl(strictOptionalProperties1.ts, 170, 15))
|
||||
}
|
||||
|
||||
function aa(input: Bar): void {
|
||||
>aa : Symbol(aa, Decl(strictOptionalProperties1.ts, 172, 1))
|
||||
>input : Symbol(input, Decl(strictOptionalProperties1.ts, 174, 12))
|
||||
>Bar : Symbol(Bar, Decl(strictOptionalProperties1.ts, 168, 1))
|
||||
|
||||
const notUndefinedVal = expectNotUndefined(input.bar);
|
||||
>notUndefinedVal : Symbol(notUndefinedVal, Decl(strictOptionalProperties1.ts, 175, 9))
|
||||
>expectNotUndefined : Symbol(expectNotUndefined, Decl(strictOptionalProperties1.ts, 161, 36))
|
||||
>input.bar : Symbol(Bar.bar, Decl(strictOptionalProperties1.ts, 170, 15))
|
||||
>input : Symbol(input, Decl(strictOptionalProperties1.ts, 174, 12))
|
||||
>bar : Symbol(Bar.bar, Decl(strictOptionalProperties1.ts, 170, 15))
|
||||
|
||||
bb(notUndefinedVal);
|
||||
>bb : Symbol(bb, Decl(strictOptionalProperties1.ts, 177, 1))
|
||||
>notUndefinedVal : Symbol(notUndefinedVal, Decl(strictOptionalProperties1.ts, 175, 9))
|
||||
}
|
||||
|
||||
declare function bb(input: number): void;
|
||||
>bb : Symbol(bb, Decl(strictOptionalProperties1.ts, 177, 1))
|
||||
>input : Symbol(input, Decl(strictOptionalProperties1.ts, 179, 20))
|
||||
|
||||
|
||||
@ -510,3 +510,176 @@ interface Test {
|
||||
>bar : string | undefined
|
||||
}
|
||||
|
||||
// Strict optional properties and inference
|
||||
|
||||
declare let ox1: { p: string };
|
||||
>ox1 : { p: string; }
|
||||
>p : string
|
||||
|
||||
declare let ox2: { p: string | undefined };
|
||||
>ox2 : { p: string | undefined; }
|
||||
>p : string | undefined
|
||||
|
||||
declare let ox3: { p?: string };
|
||||
>ox3 : { p?: string; }
|
||||
>p : string | undefined
|
||||
|
||||
declare let ox4: { p?: string | undefined };
|
||||
>ox4 : { p?: string | undefined; }
|
||||
>p : string | undefined
|
||||
|
||||
declare let tx1: [string];
|
||||
>tx1 : [string]
|
||||
|
||||
declare let tx2: [string | undefined];
|
||||
>tx2 : [string | undefined]
|
||||
|
||||
declare let tx3: [string?];
|
||||
>tx3 : [string?]
|
||||
|
||||
declare let tx4: [(string | undefined)?];
|
||||
>tx4 : [(string | undefined)?]
|
||||
|
||||
declare function f11<T>(x: { p?: T }): T;
|
||||
>f11 : <T>(x: { p?: T;}) => T
|
||||
>x : { p?: T; }
|
||||
>p : T | undefined
|
||||
|
||||
f11(ox1); // string
|
||||
>f11(ox1) : string
|
||||
>f11 : <T>(x: { p?: T; }) => T
|
||||
>ox1 : { p: string; }
|
||||
|
||||
f11(ox2); // string | undefined
|
||||
>f11(ox2) : string | undefined
|
||||
>f11 : <T>(x: { p?: T; }) => T
|
||||
>ox2 : { p: string | undefined; }
|
||||
|
||||
f11(ox3); // string
|
||||
>f11(ox3) : string
|
||||
>f11 : <T>(x: { p?: T; }) => T
|
||||
>ox3 : { p?: string; }
|
||||
|
||||
f11(ox4); // string | undefined
|
||||
>f11(ox4) : string | undefined
|
||||
>f11 : <T>(x: { p?: T; }) => T
|
||||
>ox4 : { p?: string | undefined; }
|
||||
|
||||
declare function f12<T>(x: [T?]): T;
|
||||
>f12 : <T>(x: [T?]) => T
|
||||
>x : [T?]
|
||||
|
||||
f12(tx1); // string
|
||||
>f12(tx1) : string
|
||||
>f12 : <T>(x: [T?]) => T
|
||||
>tx1 : [string]
|
||||
|
||||
f12(tx2); // string | undefined
|
||||
>f12(tx2) : string | undefined
|
||||
>f12 : <T>(x: [T?]) => T
|
||||
>tx2 : [string | undefined]
|
||||
|
||||
f12(tx3); // string
|
||||
>f12(tx3) : string
|
||||
>f12 : <T>(x: [T?]) => T
|
||||
>tx3 : [string?]
|
||||
|
||||
f12(tx4); // string | undefined
|
||||
>f12(tx4) : string | undefined
|
||||
>f12 : <T>(x: [T?]) => T
|
||||
>tx4 : [(string | undefined)?]
|
||||
|
||||
declare function f13<T>(x: Partial<T>): T;
|
||||
>f13 : <T>(x: Partial<T>) => T
|
||||
>x : Partial<T>
|
||||
|
||||
f13(ox1); // { p: string }
|
||||
>f13(ox1) : { p: string; }
|
||||
>f13 : <T>(x: Partial<T>) => T
|
||||
>ox1 : { p: string; }
|
||||
|
||||
f13(ox2); // { p: string | undefined }
|
||||
>f13(ox2) : { p: string | undefined; }
|
||||
>f13 : <T>(x: Partial<T>) => T
|
||||
>ox2 : { p: string | undefined; }
|
||||
|
||||
f13(ox3); // { p: string }
|
||||
>f13(ox3) : { p: string; }
|
||||
>f13 : <T>(x: Partial<T>) => T
|
||||
>ox3 : { p?: string; }
|
||||
|
||||
f13(ox4); // { p: string | undefined }
|
||||
>f13(ox4) : { p: string | undefined; }
|
||||
>f13 : <T>(x: Partial<T>) => T
|
||||
>ox4 : { p?: string | undefined; }
|
||||
|
||||
f13(tx1); // [string]
|
||||
>f13(tx1) : [string]
|
||||
>f13 : <T>(x: Partial<T>) => T
|
||||
>tx1 : [string]
|
||||
|
||||
f13(tx2); // [string | undefined]
|
||||
>f13(tx2) : [string | undefined]
|
||||
>f13 : <T>(x: Partial<T>) => T
|
||||
>tx2 : [string | undefined]
|
||||
|
||||
f13(tx3); // [string]
|
||||
>f13(tx3) : [string]
|
||||
>f13 : <T>(x: Partial<T>) => T
|
||||
>tx3 : [string?]
|
||||
|
||||
f13(tx4); // [string | undefined]
|
||||
>f13(tx4) : [string | undefined]
|
||||
>f13 : <T>(x: Partial<T>) => T
|
||||
>tx4 : [(string | undefined)?]
|
||||
|
||||
// Repro from #44388
|
||||
|
||||
type Undefinable<T> = T | undefined;
|
||||
>Undefinable : Undefinable<T>
|
||||
|
||||
function expectNotUndefined<T>(value: Undefinable<T>): T {
|
||||
>expectNotUndefined : <T>(value: Undefinable<T>) => T
|
||||
>value : Undefinable<T>
|
||||
|
||||
if (value === undefined) {
|
||||
>value === undefined : boolean
|
||||
>value : Undefinable<T>
|
||||
>undefined : undefined
|
||||
|
||||
throw new TypeError('value is undefined');
|
||||
>new TypeError('value is undefined') : TypeError
|
||||
>TypeError : TypeErrorConstructor
|
||||
>'value is undefined' : "value is undefined"
|
||||
}
|
||||
return value;
|
||||
>value : T
|
||||
}
|
||||
|
||||
interface Bar {
|
||||
bar?: number;
|
||||
>bar : number | undefined
|
||||
}
|
||||
|
||||
function aa(input: Bar): void {
|
||||
>aa : (input: Bar) => void
|
||||
>input : Bar
|
||||
|
||||
const notUndefinedVal = expectNotUndefined(input.bar);
|
||||
>notUndefinedVal : number
|
||||
>expectNotUndefined(input.bar) : number
|
||||
>expectNotUndefined : <T>(value: Undefinable<T>) => T
|
||||
>input.bar : number | undefined
|
||||
>input : Bar
|
||||
>bar : number | undefined
|
||||
|
||||
bb(notUndefinedVal);
|
||||
>bb(notUndefinedVal) : void
|
||||
>bb : (input: number) => void
|
||||
>notUndefinedVal : number
|
||||
}
|
||||
|
||||
declare function bb(input: number): void;
|
||||
>bb : (input: number) => void
|
||||
>input : number
|
||||
|
||||
|
||||
@ -121,3 +121,63 @@ interface Test {
|
||||
foo?: string; // Should be ok
|
||||
bar?: string | undefined; // Error
|
||||
}
|
||||
|
||||
// Strict optional properties and inference
|
||||
|
||||
declare let ox1: { p: string };
|
||||
declare let ox2: { p: string | undefined };
|
||||
declare let ox3: { p?: string };
|
||||
declare let ox4: { p?: string | undefined };
|
||||
|
||||
declare let tx1: [string];
|
||||
declare let tx2: [string | undefined];
|
||||
declare let tx3: [string?];
|
||||
declare let tx4: [(string | undefined)?];
|
||||
|
||||
declare function f11<T>(x: { p?: T }): T;
|
||||
|
||||
f11(ox1); // string
|
||||
f11(ox2); // string | undefined
|
||||
f11(ox3); // string
|
||||
f11(ox4); // string | undefined
|
||||
|
||||
declare function f12<T>(x: [T?]): T;
|
||||
|
||||
f12(tx1); // string
|
||||
f12(tx2); // string | undefined
|
||||
f12(tx3); // string
|
||||
f12(tx4); // string | undefined
|
||||
|
||||
declare function f13<T>(x: Partial<T>): T;
|
||||
|
||||
f13(ox1); // { p: string }
|
||||
f13(ox2); // { p: string | undefined }
|
||||
f13(ox3); // { p: string }
|
||||
f13(ox4); // { p: string | undefined }
|
||||
|
||||
f13(tx1); // [string]
|
||||
f13(tx2); // [string | undefined]
|
||||
f13(tx3); // [string]
|
||||
f13(tx4); // [string | undefined]
|
||||
|
||||
// Repro from #44388
|
||||
|
||||
type Undefinable<T> = T | undefined;
|
||||
|
||||
function expectNotUndefined<T>(value: Undefinable<T>): T {
|
||||
if (value === undefined) {
|
||||
throw new TypeError('value is undefined');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
interface Bar {
|
||||
bar?: number;
|
||||
}
|
||||
|
||||
function aa(input: Bar): void {
|
||||
const notUndefinedVal = expectNotUndefined(input.bar);
|
||||
bb(notUndefinedVal);
|
||||
}
|
||||
|
||||
declare function bb(input: number): void;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user