diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bdafab7161db5..6e6af7b15e642 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -43,8 +43,6 @@ namespace ts { let emptyArray: any[] = []; let emptySymbols: SymbolTable = {}; - let jsxElementClassType: Type = undefined; - let compilerOptions = host.getCompilerOptions(); let languageVersion = compilerOptions.target || ScriptTarget.ES3; let modulekind = compilerOptions.module ? compilerOptions.module : languageVersion === ScriptTarget.ES6 ? ModuleKind.ES6 : ModuleKind.None; @@ -4940,6 +4938,9 @@ namespace ts { } return objectTypeRelatedTo(source, target, /*reportErrors*/ false); } + if (source.flags & TypeFlags.TypeParameter && target.flags & TypeFlags.TypeParameter) { + return typeParameterIdenticalTo(source, target); + } if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union || source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) { if (result = eachTypeRelatedToSomeType(source, target)) { @@ -5070,6 +5071,20 @@ namespace ts { return result; } + function typeParameterIdenticalTo(source: TypeParameter, target: TypeParameter): Ternary { + if (source.symbol.name !== target.symbol.name) { + return Ternary.False; + } + // covers case when both type parameters does not have constraint (both equal to noConstraintType) + if (source.constraint === target.constraint) { + return Ternary.True; + } + if (source.constraint === noConstraintType || target.constraint === noConstraintType) { + return Ternary.False; + } + return isIdenticalTo(source.constraint, target.constraint); + } + // Determine if two object types are related by structure. First, check if the result is already available in the global cache. // Second, check if we have already started a comparison of the given two types in which case we assume the result to be true. // Third, check if both types are part of deeply nested chains of generic type instantiations and if so assume the types are @@ -5592,20 +5607,27 @@ namespace ts { return Ternary.False; } } - // Check that the two signatures have the same number of type parameters. We might consider - // also checking that any type parameter constraints match, but that would require instantiating - // the constraints with a common set of type arguments to get relatable entities in places where - // type parameters occur in the constraints. The complexity of doing that doesn't seem worthwhile, - // particularly as we're comparing erased versions of the signatures below. - if ((source.typeParameters ? source.typeParameters.length : 0) !== (target.typeParameters ? target.typeParameters.length : 0)) { + let result = Ternary.True; + if (source.typeParameters && target.typeParameters) { + if (source.typeParameters.length !== target.typeParameters.length) { + return Ternary.False; + } + for (let i = 0, len = source.typeParameters.length; i < len; ++i) { + let related = compareTypes(source.typeParameters[i], target.typeParameters[i]); + if (!related) { + return Ternary.False; + } + result &= related; + } + } + else if (source.typeParameters || target.typeParameters) { return Ternary.False; } // Spec 1.0 Section 3.8.3 & 3.8.4: // M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N source = getErasedSignature(source); target = getErasedSignature(target); - let result = Ternary.True; - const targetLen = target.parameters.length; + let targetLen = target.parameters.length; for (let i = 0; i < targetLen; i++) { let s = isRestParameterIndex(source, i) ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]); let t = isRestParameterIndex(target, i) ? getRestTypeOfSignature(target) : getTypeOfSymbol(target.parameters[i]); @@ -5906,17 +5928,6 @@ namespace ts { } function inferFromTypes(source: Type, target: Type) { - if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union || - source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) { - // Source and target are both unions or both intersections. To improve the quality of - // inferences we first reduce the types by removing constituents that are identically - // matched by a constituent in the other type. For example, when inferring from - // 'string | string[]' to 'string | T', we reduce the types to 'string[]' and 'T'. - const reducedSource = reduceUnionOrIntersectionType(source, target); - const reducedTarget = reduceUnionOrIntersectionType(target, source); - source = reducedSource; - target = reducedTarget; - } if (target.flags & TypeFlags.TypeParameter) { // If target is a type parameter, make an inference, unless the source type contains // the anyFunctionType (the wildcard type that's used to avoid contextually typing functions). @@ -5927,7 +5938,8 @@ namespace ts { if (source.flags & TypeFlags.ContainsAnyFunctionType) { return; } - const typeParameters = context.typeParameters; + + let typeParameters = context.typeParameters; for (let i = 0; i < typeParameters.length; i++) { if (target === typeParameters[i]) { let inferences = context.inferences[i]; @@ -5999,9 +6011,12 @@ namespace ts { } else { source = getApparentType(source); - if (source.flags & TypeFlags.ObjectType && (target.flags & (TypeFlags.Reference | TypeFlags.Tuple) || - (target.flags & TypeFlags.Anonymous) && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) { - // If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members + if (source.flags & TypeFlags.ObjectType && ( + target.flags & TypeFlags.Reference && (target).typeArguments || + target.flags & TypeFlags.Tuple || + target.flags & TypeFlags.Anonymous && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) { + // If source is an object type, and target is a type reference with type arguments, a tuple type, + // the type of a method, or a type literal, infer from members if (isInProcess(source, target)) { return; } @@ -6074,41 +6089,6 @@ namespace ts { } } - function typeIdenticalToSomeType(source: Type, target: UnionOrIntersectionType): boolean { - for (const t of target.types) { - if (isTypeIdenticalTo(source, t)) { - return true; - } - } - return false; - } - - /** - * Return the reduced form of the source type. This type is computed by by removing all source - * constituents that have an identical match in the target type. - */ - function reduceUnionOrIntersectionType(source: UnionOrIntersectionType, target: UnionOrIntersectionType) { - let sourceTypes = source.types; - let sourceIndex = 0; - let modified = false; - while (sourceIndex < sourceTypes.length) { - if (typeIdenticalToSomeType(sourceTypes[sourceIndex], target)) { - if (!modified) { - sourceTypes = sourceTypes.slice(0); - modified = true; - } - sourceTypes.splice(sourceIndex, 1); - } - else { - sourceIndex++; - } - } - if (modified) { - return source.flags & TypeFlags.Union ? getUnionType(sourceTypes, /*noSubtypeReduction*/ true) : getIntersectionType(sourceTypes); - } - return source; - } - function getInferenceCandidates(context: InferenceContext, index: number): Type[] { let inferences = context.inferences[index]; return inferences.primary || inferences.secondary || emptyArray; @@ -7882,6 +7862,7 @@ namespace ts { return prop || unknownSymbol; } + let jsxElementClassType: Type = undefined; function getJsxGlobalElementClassType(): Type { if (!jsxElementClassType) { jsxElementClassType = getExportedTypeFromNamespace(JsxNames.JSX, JsxNames.ElementClass); diff --git a/tests/baselines/reference/genericSignatureIdentity.js b/tests/baselines/reference/genericSignatureIdentity.js deleted file mode 100644 index 9a51a61edbd53..0000000000000 --- a/tests/baselines/reference/genericSignatureIdentity.js +++ /dev/null @@ -1,32 +0,0 @@ -//// [genericSignatureIdentity.ts] -// This test is here to remind us of our current limits of type identity checking. -// Ideally all of the below declarations would be considered different (and thus errors) -// but they aren't because we erase type parameters to type any and don't check that -// constraints are identical. - -var x: { - (x: T): T; -}; - -var x: { - (x: T): T; -}; - -var x: { - (x: T): T; -}; - -var x: { - (x: any): any; -}; - - -//// [genericSignatureIdentity.js] -// This test is here to remind us of our current limits of type identity checking. -// Ideally all of the below declarations would be considered different (and thus errors) -// but they aren't because we erase type parameters to type any and don't check that -// constraints are identical. -var x; -var x; -var x; -var x; diff --git a/tests/baselines/reference/genericSignatureIdentity.symbols b/tests/baselines/reference/genericSignatureIdentity.symbols deleted file mode 100644 index afd12ec266a18..0000000000000 --- a/tests/baselines/reference/genericSignatureIdentity.symbols +++ /dev/null @@ -1,49 +0,0 @@ -=== tests/cases/compiler/genericSignatureIdentity.ts === -// This test is here to remind us of our current limits of type identity checking. -// Ideally all of the below declarations would be considered different (and thus errors) -// but they aren't because we erase type parameters to type any and don't check that -// constraints are identical. - -var x: { ->x : Symbol(x, Decl(genericSignatureIdentity.ts, 5, 3), Decl(genericSignatureIdentity.ts, 9, 3), Decl(genericSignatureIdentity.ts, 13, 3), Decl(genericSignatureIdentity.ts, 17, 3)) - - (x: T): T; ->T : Symbol(T, Decl(genericSignatureIdentity.ts, 6, 5)) ->Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) ->x : Symbol(x, Decl(genericSignatureIdentity.ts, 6, 21)) ->T : Symbol(T, Decl(genericSignatureIdentity.ts, 6, 5)) ->T : Symbol(T, Decl(genericSignatureIdentity.ts, 6, 5)) - -}; - -var x: { ->x : Symbol(x, Decl(genericSignatureIdentity.ts, 5, 3), Decl(genericSignatureIdentity.ts, 9, 3), Decl(genericSignatureIdentity.ts, 13, 3), Decl(genericSignatureIdentity.ts, 17, 3)) - - (x: T): T; ->T : Symbol(T, Decl(genericSignatureIdentity.ts, 10, 5)) ->x : Symbol(x, Decl(genericSignatureIdentity.ts, 10, 23)) ->T : Symbol(T, Decl(genericSignatureIdentity.ts, 10, 5)) ->T : Symbol(T, Decl(genericSignatureIdentity.ts, 10, 5)) - -}; - -var x: { ->x : Symbol(x, Decl(genericSignatureIdentity.ts, 5, 3), Decl(genericSignatureIdentity.ts, 9, 3), Decl(genericSignatureIdentity.ts, 13, 3), Decl(genericSignatureIdentity.ts, 17, 3)) - - (x: T): T; ->T : Symbol(T, Decl(genericSignatureIdentity.ts, 14, 5)) ->x : Symbol(x, Decl(genericSignatureIdentity.ts, 14, 8)) ->T : Symbol(T, Decl(genericSignatureIdentity.ts, 14, 5)) ->T : Symbol(T, Decl(genericSignatureIdentity.ts, 14, 5)) - -}; - -var x: { ->x : Symbol(x, Decl(genericSignatureIdentity.ts, 5, 3), Decl(genericSignatureIdentity.ts, 9, 3), Decl(genericSignatureIdentity.ts, 13, 3), Decl(genericSignatureIdentity.ts, 17, 3)) - - (x: any): any; ->T : Symbol(T, Decl(genericSignatureIdentity.ts, 18, 5)) ->x : Symbol(x, Decl(genericSignatureIdentity.ts, 18, 8)) - -}; - diff --git a/tests/baselines/reference/genericSignatureIdentity.types b/tests/baselines/reference/genericSignatureIdentity.types deleted file mode 100644 index 9385718a36127..0000000000000 --- a/tests/baselines/reference/genericSignatureIdentity.types +++ /dev/null @@ -1,49 +0,0 @@ -=== tests/cases/compiler/genericSignatureIdentity.ts === -// This test is here to remind us of our current limits of type identity checking. -// Ideally all of the below declarations would be considered different (and thus errors) -// but they aren't because we erase type parameters to type any and don't check that -// constraints are identical. - -var x: { ->x : (x: T) => T - - (x: T): T; ->T : T ->Date : Date ->x : T ->T : T ->T : T - -}; - -var x: { ->x : (x: T) => T - - (x: T): T; ->T : T ->x : T ->T : T ->T : T - -}; - -var x: { ->x : (x: T) => T - - (x: T): T; ->T : T ->x : T ->T : T ->T : T - -}; - -var x: { ->x : (x: T) => T - - (x: any): any; ->T : T ->x : any - -}; - diff --git a/tests/baselines/reference/unionAndIntersectionInference1.js b/tests/baselines/reference/unionAndIntersectionInference1.js deleted file mode 100644 index 235eb23ebf847..0000000000000 --- a/tests/baselines/reference/unionAndIntersectionInference1.js +++ /dev/null @@ -1,113 +0,0 @@ -//// [unionAndIntersectionInference1.ts] -// Repro from #2264 - -interface Y { 'i am a very certain type': Y } -var y: Y = undefined; -function destructure( - something: a | Y, - haveValue: (value: a) => r, - haveY: (value: Y) => r -): r { - return something === y ? haveY(y) : haveValue(something); -} - -var value = Math.random() > 0.5 ? 'hey!' : undefined; - -var result = destructure(value, text => 'string', y => 'other one'); // text: string, y: Y - -// Repro from #4212 - -function isVoid(value: void | a): value is void { - return undefined; -} - -function isNonVoid(value: void | a) : value is a { - return undefined; -} - -function foo1(value: void|a): void { - if (isVoid(value)) { - value; // value is void - } else { - value; // value is a - } -} - -function baz1(value: void|a): void { - if (isNonVoid(value)) { - value; // value is a - } else { - value; // value is void - } -} - -// Repro from #5417 - -type Maybe = T | void; - -function get(x: U | void): U { - return null; // just an example -} - -let foo: Maybe; -get(foo).toUpperCase(); // Ok - -// Repro from #5456 - -interface Man { - walks: boolean; -} - -interface Bear { - roars: boolean; -} - -interface Pig { - oinks: boolean; -} - -declare function pigify(y: T & Bear): T & Pig; -declare var mbp: Man & Bear; - -pigify(mbp).oinks; // OK, mbp is treated as Pig -pigify(mbp).walks; // Ok, mbp is treated as Man - - -//// [unionAndIntersectionInference1.js] -// Repro from #2264 -var y = undefined; -function destructure(something, haveValue, haveY) { - return something === y ? haveY(y) : haveValue(something); -} -var value = Math.random() > 0.5 ? 'hey!' : undefined; -var result = destructure(value, function (text) { return 'string'; }, function (y) { return 'other one'; }); // text: string, y: Y -// Repro from #4212 -function isVoid(value) { - return undefined; -} -function isNonVoid(value) { - return undefined; -} -function foo1(value) { - if (isVoid(value)) { - value; // value is void - } - else { - value; // value is a - } -} -function baz1(value) { - if (isNonVoid(value)) { - value; // value is a - } - else { - value; // value is void - } -} -function get(x) { - return null; // just an example -} -var foo; -get(foo).toUpperCase(); // Ok -pigify(mbp).oinks; // OK, mbp is treated as Pig -pigify(mbp).walks; // Ok, mbp is treated as Man diff --git a/tests/baselines/reference/unionAndIntersectionInference1.symbols b/tests/baselines/reference/unionAndIntersectionInference1.symbols deleted file mode 100644 index 5e96790ea3470..0000000000000 --- a/tests/baselines/reference/unionAndIntersectionInference1.symbols +++ /dev/null @@ -1,202 +0,0 @@ -=== tests/cases/conformance/types/typeRelationships/typeInference/unionAndIntersectionInference1.ts === -// Repro from #2264 - -interface Y { 'i am a very certain type': Y } ->Y : Symbol(Y, Decl(unionAndIntersectionInference1.ts, 0, 0)) ->Y : Symbol(Y, Decl(unionAndIntersectionInference1.ts, 0, 0)) - -var y: Y = undefined; ->y : Symbol(y, Decl(unionAndIntersectionInference1.ts, 3, 3)) ->Y : Symbol(Y, Decl(unionAndIntersectionInference1.ts, 0, 0)) ->Y : Symbol(Y, Decl(unionAndIntersectionInference1.ts, 0, 0)) ->undefined : Symbol(undefined) - -function destructure( ->destructure : Symbol(destructure, Decl(unionAndIntersectionInference1.ts, 3, 24)) ->a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 4, 21)) ->r : Symbol(r, Decl(unionAndIntersectionInference1.ts, 4, 23)) - - something: a | Y, ->something : Symbol(something, Decl(unionAndIntersectionInference1.ts, 4, 27)) ->a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 4, 21)) ->Y : Symbol(Y, Decl(unionAndIntersectionInference1.ts, 0, 0)) - - haveValue: (value: a) => r, ->haveValue : Symbol(haveValue, Decl(unionAndIntersectionInference1.ts, 5, 21)) ->value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 6, 16)) ->a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 4, 21)) ->r : Symbol(r, Decl(unionAndIntersectionInference1.ts, 4, 23)) - - haveY: (value: Y) => r ->haveY : Symbol(haveY, Decl(unionAndIntersectionInference1.ts, 6, 31)) ->value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 7, 12)) ->Y : Symbol(Y, Decl(unionAndIntersectionInference1.ts, 0, 0)) ->r : Symbol(r, Decl(unionAndIntersectionInference1.ts, 4, 23)) - -): r { ->r : Symbol(r, Decl(unionAndIntersectionInference1.ts, 4, 23)) - - return something === y ? haveY(y) : haveValue(something); ->something : Symbol(something, Decl(unionAndIntersectionInference1.ts, 4, 27)) ->y : Symbol(y, Decl(unionAndIntersectionInference1.ts, 3, 3)) ->haveY : Symbol(haveY, Decl(unionAndIntersectionInference1.ts, 6, 31)) ->y : Symbol(y, Decl(unionAndIntersectionInference1.ts, 3, 3)) ->haveValue : Symbol(haveValue, Decl(unionAndIntersectionInference1.ts, 5, 21)) ->a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 4, 21)) ->something : Symbol(something, Decl(unionAndIntersectionInference1.ts, 4, 27)) -} - -var value = Math.random() > 0.5 ? 'hey!' : undefined; ->value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 12, 3)) ->Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --)) ->Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) ->random : Symbol(Math.random, Decl(lib.d.ts, --, --)) ->Y : Symbol(Y, Decl(unionAndIntersectionInference1.ts, 0, 0)) ->undefined : Symbol(undefined) - -var result = destructure(value, text => 'string', y => 'other one'); // text: string, y: Y ->result : Symbol(result, Decl(unionAndIntersectionInference1.ts, 14, 3)) ->destructure : Symbol(destructure, Decl(unionAndIntersectionInference1.ts, 3, 24)) ->value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 12, 3)) ->text : Symbol(text, Decl(unionAndIntersectionInference1.ts, 14, 31)) ->y : Symbol(y, Decl(unionAndIntersectionInference1.ts, 14, 49)) - -// Repro from #4212 - -function isVoid(value: void | a): value is void { ->isVoid : Symbol(isVoid, Decl(unionAndIntersectionInference1.ts, 14, 68)) ->a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 18, 16)) ->value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 18, 19)) ->a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 18, 16)) ->value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 18, 19)) - - return undefined; ->undefined : Symbol(undefined) -} - -function isNonVoid(value: void | a) : value is a { ->isNonVoid : Symbol(isNonVoid, Decl(unionAndIntersectionInference1.ts, 20, 1)) ->a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 22, 19)) ->value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 22, 22)) ->a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 22, 19)) ->value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 22, 22)) ->a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 22, 19)) - - return undefined; ->undefined : Symbol(undefined) -} - -function foo1(value: void|a): void { ->foo1 : Symbol(foo1, Decl(unionAndIntersectionInference1.ts, 24, 1)) ->a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 26, 14)) ->value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 26, 17)) ->a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 26, 14)) - - if (isVoid(value)) { ->isVoid : Symbol(isVoid, Decl(unionAndIntersectionInference1.ts, 14, 68)) ->value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 26, 17)) - - value; // value is void ->value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 26, 17)) - - } else { - value; // value is a ->value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 26, 17)) - } -} - -function baz1(value: void|a): void { ->baz1 : Symbol(baz1, Decl(unionAndIntersectionInference1.ts, 32, 1)) ->a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 34, 14)) ->value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 34, 17)) ->a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 34, 14)) - - if (isNonVoid(value)) { ->isNonVoid : Symbol(isNonVoid, Decl(unionAndIntersectionInference1.ts, 20, 1)) ->value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 34, 17)) - - value; // value is a ->value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 34, 17)) - - } else { - value; // value is void ->value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 34, 17)) - } -} - -// Repro from #5417 - -type Maybe = T | void; ->Maybe : Symbol(Maybe, Decl(unionAndIntersectionInference1.ts, 40, 1)) ->T : Symbol(T, Decl(unionAndIntersectionInference1.ts, 44, 11)) ->T : Symbol(T, Decl(unionAndIntersectionInference1.ts, 44, 11)) - -function get(x: U | void): U { ->get : Symbol(get, Decl(unionAndIntersectionInference1.ts, 44, 25)) ->U : Symbol(U, Decl(unionAndIntersectionInference1.ts, 46, 13)) ->x : Symbol(x, Decl(unionAndIntersectionInference1.ts, 46, 16)) ->U : Symbol(U, Decl(unionAndIntersectionInference1.ts, 46, 13)) ->U : Symbol(U, Decl(unionAndIntersectionInference1.ts, 46, 13)) - - return null; // just an example -} - -let foo: Maybe; ->foo : Symbol(foo, Decl(unionAndIntersectionInference1.ts, 50, 3)) ->Maybe : Symbol(Maybe, Decl(unionAndIntersectionInference1.ts, 40, 1)) - -get(foo).toUpperCase(); // Ok ->get(foo).toUpperCase : Symbol(String.toUpperCase, Decl(lib.d.ts, --, --)) ->get : Symbol(get, Decl(unionAndIntersectionInference1.ts, 44, 25)) ->foo : Symbol(foo, Decl(unionAndIntersectionInference1.ts, 50, 3)) ->toUpperCase : Symbol(String.toUpperCase, Decl(lib.d.ts, --, --)) - -// Repro from #5456 - -interface Man { ->Man : Symbol(Man, Decl(unionAndIntersectionInference1.ts, 51, 23)) - - walks: boolean; ->walks : Symbol(walks, Decl(unionAndIntersectionInference1.ts, 55, 15)) -} - -interface Bear { ->Bear : Symbol(Bear, Decl(unionAndIntersectionInference1.ts, 57, 1)) - - roars: boolean; ->roars : Symbol(roars, Decl(unionAndIntersectionInference1.ts, 59, 16)) -} - -interface Pig { ->Pig : Symbol(Pig, Decl(unionAndIntersectionInference1.ts, 61, 1)) - - oinks: boolean; ->oinks : Symbol(oinks, Decl(unionAndIntersectionInference1.ts, 63, 15)) -} - -declare function pigify(y: T & Bear): T & Pig; ->pigify : Symbol(pigify, Decl(unionAndIntersectionInference1.ts, 65, 1)) ->T : Symbol(T, Decl(unionAndIntersectionInference1.ts, 67, 24)) ->y : Symbol(y, Decl(unionAndIntersectionInference1.ts, 67, 27)) ->T : Symbol(T, Decl(unionAndIntersectionInference1.ts, 67, 24)) ->Bear : Symbol(Bear, Decl(unionAndIntersectionInference1.ts, 57, 1)) ->T : Symbol(T, Decl(unionAndIntersectionInference1.ts, 67, 24)) ->Pig : Symbol(Pig, Decl(unionAndIntersectionInference1.ts, 61, 1)) - -declare var mbp: Man & Bear; ->mbp : Symbol(mbp, Decl(unionAndIntersectionInference1.ts, 68, 11)) ->Man : Symbol(Man, Decl(unionAndIntersectionInference1.ts, 51, 23)) ->Bear : Symbol(Bear, Decl(unionAndIntersectionInference1.ts, 57, 1)) - -pigify(mbp).oinks; // OK, mbp is treated as Pig ->pigify(mbp).oinks : Symbol(Pig.oinks, Decl(unionAndIntersectionInference1.ts, 63, 15)) ->pigify : Symbol(pigify, Decl(unionAndIntersectionInference1.ts, 65, 1)) ->mbp : Symbol(mbp, Decl(unionAndIntersectionInference1.ts, 68, 11)) ->oinks : Symbol(Pig.oinks, Decl(unionAndIntersectionInference1.ts, 63, 15)) - -pigify(mbp).walks; // Ok, mbp is treated as Man ->pigify(mbp).walks : Symbol(Man.walks, Decl(unionAndIntersectionInference1.ts, 55, 15)) ->pigify : Symbol(pigify, Decl(unionAndIntersectionInference1.ts, 65, 1)) ->mbp : Symbol(mbp, Decl(unionAndIntersectionInference1.ts, 68, 11)) ->walks : Symbol(Man.walks, Decl(unionAndIntersectionInference1.ts, 55, 15)) - diff --git a/tests/baselines/reference/unionAndIntersectionInference1.types b/tests/baselines/reference/unionAndIntersectionInference1.types deleted file mode 100644 index 5d23688f0b7c3..0000000000000 --- a/tests/baselines/reference/unionAndIntersectionInference1.types +++ /dev/null @@ -1,226 +0,0 @@ -=== tests/cases/conformance/types/typeRelationships/typeInference/unionAndIntersectionInference1.ts === -// Repro from #2264 - -interface Y { 'i am a very certain type': Y } ->Y : Y ->Y : Y - -var y: Y = undefined; ->y : Y ->Y : Y ->undefined : Y ->Y : Y ->undefined : undefined - -function destructure( ->destructure : (something: a | Y, haveValue: (value: a) => r, haveY: (value: Y) => r) => r ->a : a ->r : r - - something: a | Y, ->something : a | Y ->a : a ->Y : Y - - haveValue: (value: a) => r, ->haveValue : (value: a) => r ->value : a ->a : a ->r : r - - haveY: (value: Y) => r ->haveY : (value: Y) => r ->value : Y ->Y : Y ->r : r - -): r { ->r : r - - return something === y ? haveY(y) : haveValue(something); ->something === y ? haveY(y) : haveValue(something) : r ->something === y : boolean ->something : a | Y ->y : Y ->haveY(y) : r ->haveY : (value: Y) => r ->y : Y ->haveValue(something) : r ->haveValue : (value: a) => r ->something : a ->a : a ->something : a | Y -} - -var value = Math.random() > 0.5 ? 'hey!' : undefined; ->value : string | Y ->Math.random() > 0.5 ? 'hey!' : undefined : string | Y ->Math.random() > 0.5 : boolean ->Math.random() : number ->Math.random : () => number ->Math : Math ->random : () => number ->0.5 : number ->'hey!' : string ->undefined : Y ->Y : Y ->undefined : undefined - -var result = destructure(value, text => 'string', y => 'other one'); // text: string, y: Y ->result : string ->destructure(value, text => 'string', y => 'other one') : string ->destructure : (something: a | Y, haveValue: (value: a) => r, haveY: (value: Y) => r) => r ->value : string | Y ->text => 'string' : (text: string) => string ->text : string ->'string' : string ->y => 'other one' : (y: Y) => string ->y : Y ->'other one' : string - -// Repro from #4212 - -function isVoid(value: void | a): value is void { ->isVoid : (value: void | a) => value is void ->a : a ->value : void | a ->a : a ->value : any - - return undefined; ->undefined : undefined -} - -function isNonVoid(value: void | a) : value is a { ->isNonVoid : (value: void | a) => value is a ->a : a ->value : void | a ->a : a ->value : any ->a : a - - return undefined; ->undefined : undefined -} - -function foo1(value: void|a): void { ->foo1 : (value: void | a) => void ->a : a ->value : void | a ->a : a - - if (isVoid(value)) { ->isVoid(value) : boolean ->isVoid : (value: void | a) => value is void ->value : void | a - - value; // value is void ->value : void - - } else { - value; // value is a ->value : a - } -} - -function baz1(value: void|a): void { ->baz1 : (value: void | a) => void ->a : a ->value : void | a ->a : a - - if (isNonVoid(value)) { ->isNonVoid(value) : boolean ->isNonVoid : (value: void | a) => value is a ->value : void | a - - value; // value is a ->value : a - - } else { - value; // value is void ->value : void - } -} - -// Repro from #5417 - -type Maybe = T | void; ->Maybe : T | void ->T : T ->T : T - -function get(x: U | void): U { ->get : (x: U | void) => U ->U : U ->x : U | void ->U : U ->U : U - - return null; // just an example ->null : null -} - -let foo: Maybe; ->foo : string | void ->Maybe : T | void - -get(foo).toUpperCase(); // Ok ->get(foo).toUpperCase() : string ->get(foo).toUpperCase : () => string ->get(foo) : string ->get : (x: U | void) => U ->foo : string | void ->toUpperCase : () => string - -// Repro from #5456 - -interface Man { ->Man : Man - - walks: boolean; ->walks : boolean -} - -interface Bear { ->Bear : Bear - - roars: boolean; ->roars : boolean -} - -interface Pig { ->Pig : Pig - - oinks: boolean; ->oinks : boolean -} - -declare function pigify(y: T & Bear): T & Pig; ->pigify : (y: T & Bear) => T & Pig ->T : T ->y : T & Bear ->T : T ->Bear : Bear ->T : T ->Pig : Pig - -declare var mbp: Man & Bear; ->mbp : Man & Bear ->Man : Man ->Bear : Bear - -pigify(mbp).oinks; // OK, mbp is treated as Pig ->pigify(mbp).oinks : boolean ->pigify(mbp) : Man & Pig ->pigify : (y: T & Bear) => T & Pig ->mbp : Man & Bear ->oinks : boolean - -pigify(mbp).walks; // Ok, mbp is treated as Man ->pigify(mbp).walks : boolean ->pigify(mbp) : Man & Pig ->pigify : (y: T & Bear) => T & Pig ->mbp : Man & Bear ->walks : boolean - diff --git a/tests/baselines/reference/unionAndIntersectionInference2.js b/tests/baselines/reference/unionAndIntersectionInference2.js deleted file mode 100644 index 18f08452a2ef5..0000000000000 --- a/tests/baselines/reference/unionAndIntersectionInference2.js +++ /dev/null @@ -1,45 +0,0 @@ -//// [unionAndIntersectionInference2.ts] -declare function f1(x: T | string): T; - -var a1: string; -var b1: string | string[]; -var c1: string[] | string; -var d1: string | { name: string }; -var e1: number | string | boolean; -f1(a1); // string -f1(b1); // string[] -f1(c1); // string[] -f1(d1); // { name: string } -f1(e1); // number | boolean - -declare function f2(x: T & { name: string }): T; - -var a2: string & { name: string }; -var b2: { name: string } & string[]; -var c2: string & { name: string } & number; -var d2: string & { name: string } & number & { name: string }; -f2(a2); // string -f2(b2); // string[] -f2(c2); // string & number -f2(d2); // string & number - - -//// [unionAndIntersectionInference2.js] -var a1; -var b1; -var c1; -var d1; -var e1; -f1(a1); // string -f1(b1); // string[] -f1(c1); // string[] -f1(d1); // { name: string } -f1(e1); // number | boolean -var a2; -var b2; -var c2; -var d2; -f2(a2); // string -f2(b2); // string[] -f2(c2); // string & number -f2(d2); // string & number diff --git a/tests/baselines/reference/unionAndIntersectionInference2.symbols b/tests/baselines/reference/unionAndIntersectionInference2.symbols deleted file mode 100644 index 24b1a36aa45e6..0000000000000 --- a/tests/baselines/reference/unionAndIntersectionInference2.symbols +++ /dev/null @@ -1,85 +0,0 @@ -=== tests/cases/conformance/types/typeRelationships/typeInference/unionAndIntersectionInference2.ts === -declare function f1(x: T | string): T; ->f1 : Symbol(f1, Decl(unionAndIntersectionInference2.ts, 0, 0)) ->T : Symbol(T, Decl(unionAndIntersectionInference2.ts, 0, 20)) ->x : Symbol(x, Decl(unionAndIntersectionInference2.ts, 0, 23)) ->T : Symbol(T, Decl(unionAndIntersectionInference2.ts, 0, 20)) ->T : Symbol(T, Decl(unionAndIntersectionInference2.ts, 0, 20)) - -var a1: string; ->a1 : Symbol(a1, Decl(unionAndIntersectionInference2.ts, 2, 3)) - -var b1: string | string[]; ->b1 : Symbol(b1, Decl(unionAndIntersectionInference2.ts, 3, 3)) - -var c1: string[] | string; ->c1 : Symbol(c1, Decl(unionAndIntersectionInference2.ts, 4, 3)) - -var d1: string | { name: string }; ->d1 : Symbol(d1, Decl(unionAndIntersectionInference2.ts, 5, 3)) ->name : Symbol(name, Decl(unionAndIntersectionInference2.ts, 5, 18)) - -var e1: number | string | boolean; ->e1 : Symbol(e1, Decl(unionAndIntersectionInference2.ts, 6, 3)) - -f1(a1); // string ->f1 : Symbol(f1, Decl(unionAndIntersectionInference2.ts, 0, 0)) ->a1 : Symbol(a1, Decl(unionAndIntersectionInference2.ts, 2, 3)) - -f1(b1); // string[] ->f1 : Symbol(f1, Decl(unionAndIntersectionInference2.ts, 0, 0)) ->b1 : Symbol(b1, Decl(unionAndIntersectionInference2.ts, 3, 3)) - -f1(c1); // string[] ->f1 : Symbol(f1, Decl(unionAndIntersectionInference2.ts, 0, 0)) ->c1 : Symbol(c1, Decl(unionAndIntersectionInference2.ts, 4, 3)) - -f1(d1); // { name: string } ->f1 : Symbol(f1, Decl(unionAndIntersectionInference2.ts, 0, 0)) ->d1 : Symbol(d1, Decl(unionAndIntersectionInference2.ts, 5, 3)) - -f1(e1); // number | boolean ->f1 : Symbol(f1, Decl(unionAndIntersectionInference2.ts, 0, 0)) ->e1 : Symbol(e1, Decl(unionAndIntersectionInference2.ts, 6, 3)) - -declare function f2(x: T & { name: string }): T; ->f2 : Symbol(f2, Decl(unionAndIntersectionInference2.ts, 11, 7)) ->T : Symbol(T, Decl(unionAndIntersectionInference2.ts, 13, 20)) ->x : Symbol(x, Decl(unionAndIntersectionInference2.ts, 13, 23)) ->T : Symbol(T, Decl(unionAndIntersectionInference2.ts, 13, 20)) ->name : Symbol(name, Decl(unionAndIntersectionInference2.ts, 13, 31)) ->T : Symbol(T, Decl(unionAndIntersectionInference2.ts, 13, 20)) - -var a2: string & { name: string }; ->a2 : Symbol(a2, Decl(unionAndIntersectionInference2.ts, 15, 3)) ->name : Symbol(name, Decl(unionAndIntersectionInference2.ts, 15, 18)) - -var b2: { name: string } & string[]; ->b2 : Symbol(b2, Decl(unionAndIntersectionInference2.ts, 16, 3)) ->name : Symbol(name, Decl(unionAndIntersectionInference2.ts, 16, 9)) - -var c2: string & { name: string } & number; ->c2 : Symbol(c2, Decl(unionAndIntersectionInference2.ts, 17, 3)) ->name : Symbol(name, Decl(unionAndIntersectionInference2.ts, 17, 18)) - -var d2: string & { name: string } & number & { name: string }; ->d2 : Symbol(d2, Decl(unionAndIntersectionInference2.ts, 18, 3)) ->name : Symbol(name, Decl(unionAndIntersectionInference2.ts, 18, 18)) ->name : Symbol(name, Decl(unionAndIntersectionInference2.ts, 18, 46)) - -f2(a2); // string ->f2 : Symbol(f2, Decl(unionAndIntersectionInference2.ts, 11, 7)) ->a2 : Symbol(a2, Decl(unionAndIntersectionInference2.ts, 15, 3)) - -f2(b2); // string[] ->f2 : Symbol(f2, Decl(unionAndIntersectionInference2.ts, 11, 7)) ->b2 : Symbol(b2, Decl(unionAndIntersectionInference2.ts, 16, 3)) - -f2(c2); // string & number ->f2 : Symbol(f2, Decl(unionAndIntersectionInference2.ts, 11, 7)) ->c2 : Symbol(c2, Decl(unionAndIntersectionInference2.ts, 17, 3)) - -f2(d2); // string & number ->f2 : Symbol(f2, Decl(unionAndIntersectionInference2.ts, 11, 7)) ->d2 : Symbol(d2, Decl(unionAndIntersectionInference2.ts, 18, 3)) - diff --git a/tests/baselines/reference/unionAndIntersectionInference2.types b/tests/baselines/reference/unionAndIntersectionInference2.types deleted file mode 100644 index beeb2a261f3ec..0000000000000 --- a/tests/baselines/reference/unionAndIntersectionInference2.types +++ /dev/null @@ -1,94 +0,0 @@ -=== tests/cases/conformance/types/typeRelationships/typeInference/unionAndIntersectionInference2.ts === -declare function f1(x: T | string): T; ->f1 : (x: T | string) => T ->T : T ->x : T | string ->T : T ->T : T - -var a1: string; ->a1 : string - -var b1: string | string[]; ->b1 : string | string[] - -var c1: string[] | string; ->c1 : string[] | string - -var d1: string | { name: string }; ->d1 : string | { name: string; } ->name : string - -var e1: number | string | boolean; ->e1 : number | string | boolean - -f1(a1); // string ->f1(a1) : string ->f1 : (x: T | string) => T ->a1 : string - -f1(b1); // string[] ->f1(b1) : string[] ->f1 : (x: T | string) => T ->b1 : string | string[] - -f1(c1); // string[] ->f1(c1) : string[] ->f1 : (x: T | string) => T ->c1 : string[] | string - -f1(d1); // { name: string } ->f1(d1) : { name: string; } ->f1 : (x: T | string) => T ->d1 : string | { name: string; } - -f1(e1); // number | boolean ->f1(e1) : number | boolean ->f1 : (x: T | string) => T ->e1 : number | string | boolean - -declare function f2(x: T & { name: string }): T; ->f2 : (x: T & { name: string; }) => T ->T : T ->x : T & { name: string; } ->T : T ->name : string ->T : T - -var a2: string & { name: string }; ->a2 : string & { name: string; } ->name : string - -var b2: { name: string } & string[]; ->b2 : { name: string; } & string[] ->name : string - -var c2: string & { name: string } & number; ->c2 : string & { name: string; } & number ->name : string - -var d2: string & { name: string } & number & { name: string }; ->d2 : string & { name: string; } & number & { name: string; } ->name : string ->name : string - -f2(a2); // string ->f2(a2) : string ->f2 : (x: T & { name: string; }) => T ->a2 : string & { name: string; } - -f2(b2); // string[] ->f2(b2) : string[] ->f2 : (x: T & { name: string; }) => T ->b2 : { name: string; } & string[] - -f2(c2); // string & number ->f2(c2) : string & number ->f2 : (x: T & { name: string; }) => T ->c2 : string & { name: string; } & number - -f2(d2); // string & number ->f2(d2) : string & number ->f2 : (x: T & { name: string; }) => T ->d2 : string & { name: string; } & number & { name: string; } - diff --git a/tests/baselines/reference/unionTypeParameterInference.js b/tests/baselines/reference/unionTypeParameterInference.js deleted file mode 100644 index c96e809cd4dc8..0000000000000 --- a/tests/baselines/reference/unionTypeParameterInference.js +++ /dev/null @@ -1,17 +0,0 @@ -//// [unionTypeParameterInference.ts] -// Regression test for #5861 - -interface Foo { prop: T; } - -declare function lift(value: U | Foo): Foo; - -function unlift(value: U | Foo): U { - return lift(value).prop; -} - - -//// [unionTypeParameterInference.js] -// Regression test for #5861 -function unlift(value) { - return lift(value).prop; -} diff --git a/tests/baselines/reference/unionTypeParameterInference.symbols b/tests/baselines/reference/unionTypeParameterInference.symbols deleted file mode 100644 index f2dbaac31ffb5..0000000000000 --- a/tests/baselines/reference/unionTypeParameterInference.symbols +++ /dev/null @@ -1,35 +0,0 @@ -=== tests/cases/compiler/unionTypeParameterInference.ts === -// Regression test for #5861 - -interface Foo { prop: T; } ->Foo : Symbol(Foo, Decl(unionTypeParameterInference.ts, 0, 0)) ->T : Symbol(T, Decl(unionTypeParameterInference.ts, 2, 14)) ->prop : Symbol(prop, Decl(unionTypeParameterInference.ts, 2, 18)) ->T : Symbol(T, Decl(unionTypeParameterInference.ts, 2, 14)) - -declare function lift(value: U | Foo): Foo; ->lift : Symbol(lift, Decl(unionTypeParameterInference.ts, 2, 29)) ->U : Symbol(U, Decl(unionTypeParameterInference.ts, 4, 22)) ->value : Symbol(value, Decl(unionTypeParameterInference.ts, 4, 25)) ->U : Symbol(U, Decl(unionTypeParameterInference.ts, 4, 22)) ->Foo : Symbol(Foo, Decl(unionTypeParameterInference.ts, 0, 0)) ->U : Symbol(U, Decl(unionTypeParameterInference.ts, 4, 22)) ->Foo : Symbol(Foo, Decl(unionTypeParameterInference.ts, 0, 0)) ->U : Symbol(U, Decl(unionTypeParameterInference.ts, 4, 22)) - -function unlift(value: U | Foo): U { ->unlift : Symbol(unlift, Decl(unionTypeParameterInference.ts, 4, 52)) ->U : Symbol(U, Decl(unionTypeParameterInference.ts, 6, 16)) ->value : Symbol(value, Decl(unionTypeParameterInference.ts, 6, 19)) ->U : Symbol(U, Decl(unionTypeParameterInference.ts, 6, 16)) ->Foo : Symbol(Foo, Decl(unionTypeParameterInference.ts, 0, 0)) ->U : Symbol(U, Decl(unionTypeParameterInference.ts, 6, 16)) ->U : Symbol(U, Decl(unionTypeParameterInference.ts, 6, 16)) - - return lift(value).prop; ->lift(value).prop : Symbol(Foo.prop, Decl(unionTypeParameterInference.ts, 2, 18)) ->lift : Symbol(lift, Decl(unionTypeParameterInference.ts, 2, 29)) ->value : Symbol(value, Decl(unionTypeParameterInference.ts, 6, 19)) ->prop : Symbol(Foo.prop, Decl(unionTypeParameterInference.ts, 2, 18)) -} - diff --git a/tests/baselines/reference/unionTypeParameterInference.types b/tests/baselines/reference/unionTypeParameterInference.types deleted file mode 100644 index 54eaed90ecc42..0000000000000 --- a/tests/baselines/reference/unionTypeParameterInference.types +++ /dev/null @@ -1,36 +0,0 @@ -=== tests/cases/compiler/unionTypeParameterInference.ts === -// Regression test for #5861 - -interface Foo { prop: T; } ->Foo : Foo ->T : T ->prop : T ->T : T - -declare function lift(value: U | Foo): Foo; ->lift : (value: U | Foo) => Foo ->U : U ->value : U | Foo ->U : U ->Foo : Foo ->U : U ->Foo : Foo ->U : U - -function unlift(value: U | Foo): U { ->unlift : (value: U | Foo) => U ->U : U ->value : U | Foo ->U : U ->Foo : Foo ->U : U ->U : U - - return lift(value).prop; ->lift(value).prop : U ->lift(value) : Foo ->lift : (value: U | Foo) => Foo ->value : U | Foo ->prop : U -} - diff --git a/tests/cases/compiler/genericSignatureIdentity.ts b/tests/cases/compiler/genericSignatureIdentity.ts deleted file mode 100644 index c685b8cc57363..0000000000000 --- a/tests/cases/compiler/genericSignatureIdentity.ts +++ /dev/null @@ -1,20 +0,0 @@ -// This test is here to remind us of our current limits of type identity checking. -// Ideally all of the below declarations would be considered different (and thus errors) -// but they aren't because we erase type parameters to type any and don't check that -// constraints are identical. - -var x: { - (x: T): T; -}; - -var x: { - (x: T): T; -}; - -var x: { - (x: T): T; -}; - -var x: { - (x: any): any; -}; diff --git a/tests/cases/compiler/unionTypeParameterInference.ts b/tests/cases/compiler/unionTypeParameterInference.ts deleted file mode 100644 index 79c4f3cc0e52a..0000000000000 --- a/tests/cases/compiler/unionTypeParameterInference.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Regression test for #5861 - -interface Foo { prop: T; } - -declare function lift(value: U | Foo): Foo; - -function unlift(value: U | Foo): U { - return lift(value).prop; -} diff --git a/tests/cases/conformance/types/typeRelationships/typeInference/unionAndIntersectionInference1.ts b/tests/cases/conformance/types/typeRelationships/typeInference/unionAndIntersectionInference1.ts deleted file mode 100644 index 7066c3e679084..0000000000000 --- a/tests/cases/conformance/types/typeRelationships/typeInference/unionAndIntersectionInference1.ts +++ /dev/null @@ -1,72 +0,0 @@ -// Repro from #2264 - -interface Y { 'i am a very certain type': Y } -var y: Y = undefined; -function destructure( - something: a | Y, - haveValue: (value: a) => r, - haveY: (value: Y) => r -): r { - return something === y ? haveY(y) : haveValue(something); -} - -var value = Math.random() > 0.5 ? 'hey!' : undefined; - -var result = destructure(value, text => 'string', y => 'other one'); // text: string, y: Y - -// Repro from #4212 - -function isVoid(value: void | a): value is void { - return undefined; -} - -function isNonVoid(value: void | a) : value is a { - return undefined; -} - -function foo1(value: void|a): void { - if (isVoid(value)) { - value; // value is void - } else { - value; // value is a - } -} - -function baz1(value: void|a): void { - if (isNonVoid(value)) { - value; // value is a - } else { - value; // value is void - } -} - -// Repro from #5417 - -type Maybe = T | void; - -function get(x: U | void): U { - return null; // just an example -} - -let foo: Maybe; -get(foo).toUpperCase(); // Ok - -// Repro from #5456 - -interface Man { - walks: boolean; -} - -interface Bear { - roars: boolean; -} - -interface Pig { - oinks: boolean; -} - -declare function pigify(y: T & Bear): T & Pig; -declare var mbp: Man & Bear; - -pigify(mbp).oinks; // OK, mbp is treated as Pig -pigify(mbp).walks; // Ok, mbp is treated as Man diff --git a/tests/cases/conformance/types/typeRelationships/typeInference/unionAndIntersectionInference2.ts b/tests/cases/conformance/types/typeRelationships/typeInference/unionAndIntersectionInference2.ts deleted file mode 100644 index 1b6a928ce028c..0000000000000 --- a/tests/cases/conformance/types/typeRelationships/typeInference/unionAndIntersectionInference2.ts +++ /dev/null @@ -1,23 +0,0 @@ -declare function f1(x: T | string): T; - -var a1: string; -var b1: string | string[]; -var c1: string[] | string; -var d1: string | { name: string }; -var e1: number | string | boolean; -f1(a1); // string -f1(b1); // string[] -f1(c1); // string[] -f1(d1); // { name: string } -f1(e1); // number | boolean - -declare function f2(x: T & { name: string }): T; - -var a2: string & { name: string }; -var b2: { name: string } & string[]; -var c2: string & { name: string } & number; -var d2: string & { name: string } & number & { name: string }; -f2(a2); // string -f2(b2); // string[] -f2(c2); // string & number -f2(d2); // string & number