diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7d4faf5e8af..32e402aa7d7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -45918,14 +45918,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const narrowedTypeParameters: TypeParameter[] = []; const narrowedTypes: Type[] = []; - for (const [typeParam, symbol, reference] of narrowableTypeParameters) { - const narrowReference = factory.cloneNode(reference); // Construct a reference that can be narrowed. - // Don't reuse the original reference's node id, - // because that could cause us to get a type that was cached for the original reference. - narrowReference.id = undefined; + for (const [typeParam, symbol, narrowReference] of narrowableTypeParameters) { + // Do not reuse node ids, as that could lead us to wrongly reuse cached information. + resetNodeId(narrowReference); // Set the symbol of the synthetic reference. // This allows us to get the type of the reference at a location where the reference is possibly shadowed. - getNodeLinks(narrowReference).resolvedSymbol = symbol; + let baseReference: Node = narrowReference; + while (isAccessExpression(baseReference)) { + baseReference = baseReference.expression; + } + getNodeLinks(baseReference).resolvedSymbol = symbol; setParent(narrowReference, narrowPosition.parent); narrowReference.flowNode = narrowFlowNode; const initialType = getNarrowableTypeForReference(typeParam, narrowReference, /*checkMode*/ undefined, /*forReturnTypeNarrowing*/ true); @@ -45974,13 +45976,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkTypeAssignableToAndOptionallyElaborate(narrowedUnwrappedExprType, narrowedReturnType, errorNode, effectiveExpr); } + // Reset node ids of cloned nodes. + function resetNodeId(node: Node): void { + node.id = undefined; + forEachChildRecursively(node, resetNodeId); + } + + type NarrowableReference = Identifier | ElementAccessExpression | PropertyAccessExpression; /** * Narrowable type parameters are type parameters that: * (1) have a narrowable constraint; * (2) are syntactically used as the type of a single parameter in the function, and nothing else */ - function getNarrowableTypeParameters(candidates: TypeParameter[]): [TypeParameter, Symbol, Identifier][] { - const narrowableParams: [TypeParameter, Symbol, Identifier][] = []; + function getNarrowableTypeParameters(candidates: TypeParameter[]): [TypeParameter, Symbol, NarrowableReference][] { + const narrowableParams: [TypeParameter, Symbol, NarrowableReference][] = []; for (const typeParam of candidates) { const constraint = getConstraintOfTypeParameter(typeParam); if (!constraint || !isNarrowableTypeParameterConstraint(constraint)) continue; @@ -46008,9 +46017,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { paramReference = paramDecl; } } - if (!hasInvalidReference && referencePath) { // Valid type parameter reference: type parameter is narrowable - const symbol = getResolvedSymbol(reference); // >> TODO: construct reference; get its symbol - if (symbol !== unknownSymbol) narrowableParams.push([typeParam, symbol, reference]); + if (!hasInvalidReference && referencePath) { + const symbolAndReference = constructNarrowableReference(paramReference!, referencePath); + if (symbolAndReference) { + if (symbolAndReference[0] && symbolAndReference[0] !== unknownSymbol) { + narrowableParams.push([typeParam, symbolAndReference[0], symbolAndReference[1]]); + } + } } } } @@ -46062,10 +46075,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const typeArgs = (typeNode as TypeReferenceNode).typeArguments; // Type arguments that reference `T` - const typeArgsReferenced = typeArgs?.filter(node => isTypeParameterReferenced(typeParam, node)) - if (!typeArgsReferenced || typeArgsReferenced.length == 0) return true; // Type reference unrelated to `T` - if (typeArgsReferenced && typeArgsReferenced.length > 1) return false; // e.g. `Foo` - const typeArg = typeArgsReferenced[0]; + const typeArgsReferencingT = typeArgs?.filter(node => isTypeParameterReferenced(typeParam, node)) + if (!typeArgsReferencingT || typeArgsReferencingT.length == 0) return true; // Type reference unrelated to `T` + if (typeArgsReferencingT && typeArgsReferencingT.length > 1) return false; // e.g. `Foo` + const typeArg = typeArgsReferencingT[0]; if (!(typeArg.kind & SyntaxKind.TypeReference)) return false; // e.g. `Foo, ...>` if (!type.symbol || !type.symbol.declarations || type.symbol.declarations.length != 1) return false; const typeDeclaration = type.symbol.declarations[0]; @@ -46081,7 +46094,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const typeArgIndex = typeArgs!.findIndex(arg => arg === typeArg); const matchingTypeParamDecl = aliasDeclaration.typeParameters?.[typeArgIndex]; if (!matchingTypeParamDecl) return false; // Shouldn't happen, unless there is an error in the input program. - const matchingTypeParam = getTypeOfSymbol(getSymbolOfDeclaration(matchingTypeParamDecl)) as TypeParameter; // >> TODO: better way? + const matchingTypeParam = getDeclaredTypeOfTypeParameter(matchingTypeParamDecl.symbol); return getValidTypeParameterReference(typeDeclaration, matchingTypeParam, path); case SyntaxKind.InterfaceDeclaration: const extendsTypes = flatMap((typeNode as InterfaceDeclaration).heritageClauses, clause => clause.types); @@ -46129,13 +46142,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!isPropertySignature(member)) { return false; // Unsupported reference to `T`, e.g. `[s: string]: T`. } - if (!isIdentifier(member.name) && !isStringLiteral(member.name)) { // >> TODO: support number literal? others? + if (!isIdentifier(member.name) && !isStringLiteral(member.name)) { // >> TODO: support others e.g. computed property? return false; // Unsupported property name, e.g. `[c]: T` } if (member.questionToken) { // >> TODO: account for property optionality } - const result = getValidTypeParameterReference(member.type!, typeParam, [member.name, ...path]) + const result = getValidTypeParameterReference(member.type!, typeParam, [...path, member.name]) if (!result) { return false; } @@ -46157,14 +46170,66 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // `constructNarrowableReference(`param: { "a b": T }`, ["a b"])` ==> `param["a b"]` // `constructNarrowableReference(`{ b }: { b: T }`, [`b`])` ==> `b` // `constructNarrowableReference(`{ a }: { a: { b: T } }`, [`a`, `b`])` ==> `a.b` - function constructNarrowableReference(paramDecl: ParameterDeclaration, path: Name[]): PropertyAccessExpression { - // >> TODO: impl - // >> TODO: consider if we'll be able to get the symbol at this constructed location... + // `constructNarrowableReference(`{ a: { b }} : { a: { b: T }} }`, [`a`, `b`])` ==> `b` + function constructNarrowableReference(paramDecl: ParameterDeclaration, path: Name[]): [Symbol, NarrowableReference] | undefined { + let currentName = paramDecl.name; + let i = 0; + for (; i < path.length; i++) { + if (isIdentifier(currentName)) { + break; + } + else if (isObjectBindingPattern(currentName)) { + const name = path[i]; + let nameText: __String | undefined; + if (isIdentifier(name)) nameText = name.escapedText + else { + const rawText = getLiteralPropertyNameText(name); + if (rawText) nameText = escapeLeadingUnderscores(rawText); + } + // Find binding element corresponding to `name`. + const element = currentName.elements.find(element => { + const propertyName = getDestructuringPropertyName(element); + const propertyNameText = propertyName && escapeLeadingUnderscores(propertyName); + return nameText && propertyNameText && nameText === propertyNameText; + }); + if (!element) { + return undefined; // Shouldn't happen unless the program has errors. + } + currentName = element.name; + } + else { + // Unsupported cases. Shouldn't happen unless the program has errors. + return undefined; + } + } + if (!isIdentifier(currentName)) { + return undefined; // Shouldn't happen unless the program has errors. + } + let result: NarrowableReference = factory.cloneNode(currentName); + const initialSymbol = getSymbolOfDeclaration(currentName.parent as ParameterDeclaration | BindingElement); + for (let j = i; j < path.length; j++) { + result = addName(result, path[j]); + } + return [initialSymbol, result]; + } + + function addName(exp: NarrowableReference, name: Name): NarrowableReference { + name = factory.cloneNode(name); + if (isIdentifier(name)) { + const accessExp = factory.createPropertyAccessExpression(exp, name); + setParent(name, accessExp); + setParent(exp, accessExp); + return accessExp; + } + else { + const accessExp = factory.createElementAccessExpression(exp, name); + setParent(name, accessExp); + setParent(exp, accessExp); + return accessExp; + } } } - - /** * Determines if the type parameter constraint allows for narrowing of that type parameter. * This is true if: diff --git a/tests/baselines/reference/dependentReturnType11.errors.txt b/tests/baselines/reference/dependentReturnType11.errors.txt new file mode 100644 index 00000000000..463701c8901 --- /dev/null +++ b/tests/baselines/reference/dependentReturnType11.errors.txt @@ -0,0 +1,275 @@ +dependentReturnType11.ts(36,34): error TS2339: Property 'prop1' does not exist on type 'Boolean'. +dependentReturnType11.ts(37,20): error TS2322: Type '1' is not assignable to type 'Ret'. +dependentReturnType11.ts(37,24): error TS2322: Type '2' is not assignable to type 'Ret'. +dependentReturnType11.ts(72,25): error TS2322: Type '1' is not assignable to type 'Ret'. +dependentReturnType11.ts(72,29): error TS2322: Type '2' is not assignable to type 'Ret'. +dependentReturnType11.ts(93,25): error TS2322: Type '1' is not assignable to type 'Ret'. +dependentReturnType11.ts(93,29): error TS2322: Type '2' is not assignable to type 'Ret'. +dependentReturnType11.ts(110,19): error TS2322: Type '1' is not assignable to type 'Ret'. +dependentReturnType11.ts(110,23): error TS2322: Type '2' is not assignable to type 'Ret'. +dependentReturnType11.ts(114,23): error TS2322: Type '1' is not assignable to type 'Ret'. +dependentReturnType11.ts(114,27): error TS2322: Type '2' is not assignable to type 'Ret'. +dependentReturnType11.ts(118,23): error TS2322: Type '1' is not assignable to type 'Ret'. +dependentReturnType11.ts(118,27): error TS2322: Type '2' is not assignable to type 'Ret'. +dependentReturnType11.ts(136,25): error TS2322: Type '1' is not assignable to type 'Ret'. +dependentReturnType11.ts(136,29): error TS2322: Type '2' is not assignable to type 'Ret'. +dependentReturnType11.ts(144,25): error TS2322: Type '1' is not assignable to type 'Ret'. +dependentReturnType11.ts(144,29): error TS2322: Type '2' is not assignable to type 'Ret'. +dependentReturnType11.ts(152,25): error TS2322: Type '1' is not assignable to type 'Ret'. +dependentReturnType11.ts(152,29): error TS2322: Type '2' is not assignable to type 'Ret'. +dependentReturnType11.ts(205,13): error TS2322: Type '1' is not assignable to type 'Ret'. +dependentReturnType11.ts(207,9): error TS2322: Type '2' is not assignable to type 'Ret'. + + +==== dependentReturnType11.ts (21 errors) ==== + type Ret = + T extends true ? 1 : + T extends false ? 2 : + never; + + // Tests for constructing narrowable reference. + + function f1(param: T): Ret { + return param ? 1 : 2; + } + + function f2(param: { prop: T }): Ret { + return param.prop ? 1 : 2; + } + + function f3({ prop }: { prop: T }): Ret { + return prop ? 1 : 2; + } + + function f4({ prop1 }: { prop1: { prop2: T } }): Ret { + return prop1.prop2 ? 1 : 2; + } + + function f5(param: { prop1: { prop2: T } }): Ret { + return param.prop1.prop2 ? 1 : 2; + } + + function f6({ prop1: { prop2: a } }: { prop1: { prop2: T } }): Ret { + return a ? 1 : 2; + } + + function f7({ prop1: { prop2 } }: { prop1: { prop2: T } }): Ret { + return prop2 ? 1 : 2; + } + + function f8({ prop1 }: T): Ret { // Bad. + ~~~~~ +!!! error TS2339: Property 'prop1' does not exist on type 'Boolean'. + return prop1 ? 1 : 2; + ~ +!!! error TS2322: Type '1' is not assignable to type 'Ret'. + ~ +!!! error TS2322: Type '2' is not assignable to type 'Ret'. + } + + function f9(param: { "some prop": T }): Ret { + return param["some prop"] ? 1 : 2; + } + + // Tests for detection of valid narrowable type parameter references. + + function g1(param: T): Ret { + return param ? 1 : 2; + } + + function g2(param: { prop: T }): Ret { + return param.prop ? 1 : 2; + } + + class Dog { + bark(): void {} + } + + class Cat { + meow(): void {} + + } + + type Type1 = { prop: T, prop2: Cat | Dog } + + function g3(param: Type1): Ret { + return param.prop ? 1 : 2; + } + + type TypeUnused = string; + + function g4(param: Type1, other: TypeUnused): Ret { // Bad. + return param.prop ? 1 : 2; + ~ +!!! error TS2322: Type '1' is not assignable to type 'Ret'. + ~ +!!! error TS2322: Type '2' is not assignable to type 'Ret'. + } + + interface Type2 { + prop: T, + [s: string]: boolean | undefined, + } + + function g5(param: Type2): Ret { + return param.prop ? 1 : 2; + } + + interface Type3 { + prop: T, + } + + interface Type3 { + prop2: Cat | Dog, + } + + function g6(param: Type3): Ret { // Unsupported for now: interface merging. + return param.prop ? 1 : 2; + ~ +!!! error TS2322: Type '1' is not assignable to type 'Ret'. + ~ +!!! error TS2322: Type '2' is not assignable to type 'Ret'. + } + + type Type4 = { + prop: T, + prop2: S[], + } + + function g7(param: Type4): Ret { + return param.prop ? 1 : 2; + } + + function g8(param: Type1 & { prop2: Cat | Dog }): Ret { + return param.prop ? 1 : 2; + } + + function g9([ prop ]: [T]): Ret { // Unsupported. + return prop ? 1 : 2; + ~ +!!! error TS2322: Type '1' is not assignable to type 'Ret'. + ~ +!!! error TS2322: Type '2' is not assignable to type 'Ret'. + } + + function g10(param: [T]): Ret { // Unsupported. + return param[0] ? 1 : 2; + ~ +!!! error TS2322: Type '1' is not assignable to type 'Ret'. + ~ +!!! error TS2322: Type '2' is not assignable to type 'Ret'. + } + + function g11(param: T[]): Ret { // Bad. + return param[0] ? 1 : 2; + ~ +!!! error TS2322: Type '1' is not assignable to type 'Ret'. + ~ +!!! error TS2322: Type '2' is not assignable to type 'Ret'. + } + + type Type5 = { + prop: S, + prop2: string[], + } + + function g12(param: Type5): Ret { + return param.prop ? 1 : 2; + } + + type Type6 = { + prop: S, + prop2: S[], + } + + function g13(param: Type6): Ret { // Bad. + return param.prop ? 1 : 2; + ~ +!!! error TS2322: Type '1' is not assignable to type 'Ret'. + ~ +!!! error TS2322: Type '2' is not assignable to type 'Ret'. + } + + type Type7 = { + [Key in "prop"]: T + } + + function g14(param: Type7): Ret { // Unsupported. + return param.prop ? 1 : 2; + ~ +!!! error TS2322: Type '1' is not assignable to type 'Ret'. + ~ +!!! error TS2322: Type '2' is not assignable to type 'Ret'. + } + + class Class1 { + prop!: T; + } + + function g15(param: Class1): Ret { // Unsupported. + return param.prop ? 1 : 2; + ~ +!!! error TS2322: Type '1' is not assignable to type 'Ret'. + ~ +!!! error TS2322: Type '2' is not assignable to type 'Ret'. + } + + type Type8 = { + prop: T, + } + + type Type9 = { + prop2: T, + } + + function g16(param: Type8["prop2"]>): Ret { // Unsupported. + return param.prop ? 1 : 2; + } + + // Tests for shadowing and resolving the constructed narrowable reference. + + function h1(param: T): Ret { + if (param) { + const param = false; + return 1; + } + return 2; + } + + function h2({ prop }: { prop: T}): Ret { + if (prop) { + const prop = false; + return 1; + } + return 2; + } + + function h3(param: { prop: T}): Ret { + if (param.prop) { + const param = { prop: false }; + return 1; + } + return 2; + } + + function h4(param: { "some prop": T }): Ret { + if (param["some prop"]) { + const param = { "some prop": false }; + return 1; + } + return 2; + } + + function h5(param: T): Ret { + { + const param = true; + if (param) { + return 1; // Bad. + ~~~~~~ +!!! error TS2322: Type '1' is not assignable to type 'Ret'. + } + return 2; + ~~~~~~ +!!! error TS2322: Type '2' is not assignable to type 'Ret'. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/dependentReturnType11.symbols b/tests/baselines/reference/dependentReturnType11.symbols new file mode 100644 index 00000000000..a7a9c4675a1 --- /dev/null +++ b/tests/baselines/reference/dependentReturnType11.symbols @@ -0,0 +1,627 @@ +//// [tests/cases/compiler/dependentReturnType11.ts] //// + +=== dependentReturnType11.ts === +type Ret = +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 0, 9)) + + T extends true ? 1 : +>T : Symbol(T, Decl(dependentReturnType11.ts, 0, 9)) + + T extends false ? 2 : +>T : Symbol(T, Decl(dependentReturnType11.ts, 0, 9)) + + never; + +// Tests for constructing narrowable reference. + +function f1(param: T): Ret { +>f1 : Symbol(f1, Decl(dependentReturnType11.ts, 3, 10)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 7, 12)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 7, 31)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 7, 12)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 7, 12)) + + return param ? 1 : 2; +>param : Symbol(param, Decl(dependentReturnType11.ts, 7, 31)) +} + +function f2(param: { prop: T }): Ret { +>f2 : Symbol(f2, Decl(dependentReturnType11.ts, 9, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 11, 12)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 11, 31)) +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 11, 39)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 11, 12)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 11, 12)) + + return param.prop ? 1 : 2; +>param.prop : Symbol(prop, Decl(dependentReturnType11.ts, 11, 39)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 11, 31)) +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 11, 39)) +} + +function f3({ prop }: { prop: T }): Ret { +>f3 : Symbol(f3, Decl(dependentReturnType11.ts, 13, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 15, 12)) +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 15, 32)) +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 15, 42)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 15, 12)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 15, 12)) + + return prop ? 1 : 2; +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 15, 32)) +} + +function f4({ prop1 }: { prop1: { prop2: T } }): Ret { +>f4 : Symbol(f4, Decl(dependentReturnType11.ts, 17, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 19, 12)) +>prop1 : Symbol(prop1, Decl(dependentReturnType11.ts, 19, 32)) +>prop1 : Symbol(prop1, Decl(dependentReturnType11.ts, 19, 43)) +>prop2 : Symbol(prop2, Decl(dependentReturnType11.ts, 19, 52)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 19, 12)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 19, 12)) + + return prop1.prop2 ? 1 : 2; +>prop1.prop2 : Symbol(prop2, Decl(dependentReturnType11.ts, 19, 52)) +>prop1 : Symbol(prop1, Decl(dependentReturnType11.ts, 19, 32)) +>prop2 : Symbol(prop2, Decl(dependentReturnType11.ts, 19, 52)) +} + +function f5(param: { prop1: { prop2: T } }): Ret { +>f5 : Symbol(f5, Decl(dependentReturnType11.ts, 21, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 23, 12)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 23, 31)) +>prop1 : Symbol(prop1, Decl(dependentReturnType11.ts, 23, 39)) +>prop2 : Symbol(prop2, Decl(dependentReturnType11.ts, 23, 48)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 23, 12)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 23, 12)) + + return param.prop1.prop2 ? 1 : 2; +>param.prop1.prop2 : Symbol(prop2, Decl(dependentReturnType11.ts, 23, 48)) +>param.prop1 : Symbol(prop1, Decl(dependentReturnType11.ts, 23, 39)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 23, 31)) +>prop1 : Symbol(prop1, Decl(dependentReturnType11.ts, 23, 39)) +>prop2 : Symbol(prop2, Decl(dependentReturnType11.ts, 23, 48)) +} + +function f6({ prop1: { prop2: a } }: { prop1: { prop2: T } }): Ret { +>f6 : Symbol(f6, Decl(dependentReturnType11.ts, 25, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 27, 12)) +>prop1 : Symbol(prop1, Decl(dependentReturnType11.ts, 27, 57)) +>prop2 : Symbol(prop2, Decl(dependentReturnType11.ts, 27, 66)) +>a : Symbol(a, Decl(dependentReturnType11.ts, 27, 41)) +>prop1 : Symbol(prop1, Decl(dependentReturnType11.ts, 27, 57)) +>prop2 : Symbol(prop2, Decl(dependentReturnType11.ts, 27, 66)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 27, 12)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 27, 12)) + + return a ? 1 : 2; +>a : Symbol(a, Decl(dependentReturnType11.ts, 27, 41)) +} + +function f7({ prop1: { prop2 } }: { prop1: { prop2: T } }): Ret { +>f7 : Symbol(f7, Decl(dependentReturnType11.ts, 29, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 31, 12)) +>prop1 : Symbol(prop1, Decl(dependentReturnType11.ts, 31, 54)) +>prop2 : Symbol(prop2, Decl(dependentReturnType11.ts, 31, 41)) +>prop1 : Symbol(prop1, Decl(dependentReturnType11.ts, 31, 54)) +>prop2 : Symbol(prop2, Decl(dependentReturnType11.ts, 31, 63)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 31, 12)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 31, 12)) + + return prop2 ? 1 : 2; +>prop2 : Symbol(prop2, Decl(dependentReturnType11.ts, 31, 41)) +} + +function f8({ prop1 }: T): Ret { // Bad. +>f8 : Symbol(f8, Decl(dependentReturnType11.ts, 33, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 35, 12)) +>prop1 : Symbol(prop1, Decl(dependentReturnType11.ts, 35, 32)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 35, 12)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 35, 12)) + + return prop1 ? 1 : 2; +>prop1 : Symbol(prop1, Decl(dependentReturnType11.ts, 35, 32)) +} + +function f9(param: { "some prop": T }): Ret { +>f9 : Symbol(f9, Decl(dependentReturnType11.ts, 37, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 39, 12)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 39, 31)) +>"some prop" : Symbol("some prop", Decl(dependentReturnType11.ts, 39, 39)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 39, 12)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 39, 12)) + + return param["some prop"] ? 1 : 2; +>param : Symbol(param, Decl(dependentReturnType11.ts, 39, 31)) +>"some prop" : Symbol("some prop", Decl(dependentReturnType11.ts, 39, 39)) +} + +// Tests for detection of valid narrowable type parameter references. + +function g1(param: T): Ret { +>g1 : Symbol(g1, Decl(dependentReturnType11.ts, 41, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 45, 12)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 45, 31)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 45, 12)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 45, 12)) + + return param ? 1 : 2; +>param : Symbol(param, Decl(dependentReturnType11.ts, 45, 31)) +} + +function g2(param: { prop: T }): Ret { +>g2 : Symbol(g2, Decl(dependentReturnType11.ts, 47, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 49, 12)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 49, 31)) +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 49, 39)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 49, 12)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 49, 12)) + + return param.prop ? 1 : 2; +>param.prop : Symbol(prop, Decl(dependentReturnType11.ts, 49, 39)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 49, 31)) +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 49, 39)) +} + +class Dog { +>Dog : Symbol(Dog, Decl(dependentReturnType11.ts, 51, 1)) + + bark(): void {} +>bark : Symbol(Dog.bark, Decl(dependentReturnType11.ts, 53, 11)) +} + +class Cat { +>Cat : Symbol(Cat, Decl(dependentReturnType11.ts, 55, 1)) + + meow(): void {} +>meow : Symbol(Cat.meow, Decl(dependentReturnType11.ts, 57, 11)) + +} + +type Type1 = { prop: T, prop2: Cat | Dog } +>Type1 : Symbol(Type1, Decl(dependentReturnType11.ts, 60, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 62, 11)) +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 62, 17)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 62, 11)) +>prop2 : Symbol(prop2, Decl(dependentReturnType11.ts, 62, 26)) +>Cat : Symbol(Cat, Decl(dependentReturnType11.ts, 55, 1)) +>Dog : Symbol(Dog, Decl(dependentReturnType11.ts, 51, 1)) + +function g3(param: Type1): Ret { +>g3 : Symbol(g3, Decl(dependentReturnType11.ts, 62, 45)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 64, 12)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 64, 31)) +>Type1 : Symbol(Type1, Decl(dependentReturnType11.ts, 60, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 64, 12)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 64, 12)) + + return param.prop ? 1 : 2; +>param.prop : Symbol(prop, Decl(dependentReturnType11.ts, 62, 17)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 64, 31)) +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 62, 17)) +} + +type TypeUnused = string; +>TypeUnused : Symbol(TypeUnused, Decl(dependentReturnType11.ts, 66, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 68, 16)) + +function g4(param: Type1, other: TypeUnused): Ret { // Bad. +>g4 : Symbol(g4, Decl(dependentReturnType11.ts, 68, 28)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 70, 12)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 70, 31)) +>Type1 : Symbol(Type1, Decl(dependentReturnType11.ts, 60, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 70, 12)) +>other : Symbol(other, Decl(dependentReturnType11.ts, 70, 47)) +>TypeUnused : Symbol(TypeUnused, Decl(dependentReturnType11.ts, 66, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 70, 12)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 70, 12)) + + return param.prop ? 1 : 2; +>param.prop : Symbol(prop, Decl(dependentReturnType11.ts, 62, 17)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 70, 31)) +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 62, 17)) +} + +interface Type2 { +>Type2 : Symbol(Type2, Decl(dependentReturnType11.ts, 72, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 74, 16)) + + prop: T, +>prop : Symbol(Type2.prop, Decl(dependentReturnType11.ts, 74, 36)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 74, 16)) + + [s: string]: boolean | undefined, +>s : Symbol(s, Decl(dependentReturnType11.ts, 76, 5)) +} + +function g5(param: Type2): Ret { +>g5 : Symbol(g5, Decl(dependentReturnType11.ts, 77, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 79, 12)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 79, 31)) +>Type2 : Symbol(Type2, Decl(dependentReturnType11.ts, 72, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 79, 12)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 79, 12)) + + return param.prop ? 1 : 2; +>param.prop : Symbol(Type2.prop, Decl(dependentReturnType11.ts, 74, 36)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 79, 31)) +>prop : Symbol(Type2.prop, Decl(dependentReturnType11.ts, 74, 36)) +} + +interface Type3 { +>Type3 : Symbol(Type3, Decl(dependentReturnType11.ts, 81, 1), Decl(dependentReturnType11.ts, 85, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 83, 16), Decl(dependentReturnType11.ts, 87, 16)) + + prop: T, +>prop : Symbol(Type3.prop, Decl(dependentReturnType11.ts, 83, 36)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 83, 16), Decl(dependentReturnType11.ts, 87, 16)) +} + +interface Type3 { +>Type3 : Symbol(Type3, Decl(dependentReturnType11.ts, 81, 1), Decl(dependentReturnType11.ts, 85, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 83, 16), Decl(dependentReturnType11.ts, 87, 16)) + + prop2: Cat | Dog, +>prop2 : Symbol(Type3.prop2, Decl(dependentReturnType11.ts, 87, 36)) +>Cat : Symbol(Cat, Decl(dependentReturnType11.ts, 55, 1)) +>Dog : Symbol(Dog, Decl(dependentReturnType11.ts, 51, 1)) +} + +function g6(param: Type3): Ret { // Unsupported for now: interface merging. +>g6 : Symbol(g6, Decl(dependentReturnType11.ts, 89, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 91, 12)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 91, 31)) +>Type3 : Symbol(Type3, Decl(dependentReturnType11.ts, 81, 1), Decl(dependentReturnType11.ts, 85, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 91, 12)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 91, 12)) + + return param.prop ? 1 : 2; +>param.prop : Symbol(Type3.prop, Decl(dependentReturnType11.ts, 83, 36)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 91, 31)) +>prop : Symbol(Type3.prop, Decl(dependentReturnType11.ts, 83, 36)) +} + +type Type4 = { +>Type4 : Symbol(Type4, Decl(dependentReturnType11.ts, 93, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 95, 11)) +>S : Symbol(S, Decl(dependentReturnType11.ts, 95, 13)) + + prop: T, +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 95, 20)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 95, 11)) + + prop2: S[], +>prop2 : Symbol(prop2, Decl(dependentReturnType11.ts, 96, 12)) +>S : Symbol(S, Decl(dependentReturnType11.ts, 95, 13)) +} + +function g7(param: Type4): Ret { +>g7 : Symbol(g7, Decl(dependentReturnType11.ts, 98, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 100, 12)) +>S : Symbol(S, Decl(dependentReturnType11.ts, 100, 30)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 100, 34)) +>Type4 : Symbol(Type4, Decl(dependentReturnType11.ts, 93, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 100, 12)) +>S : Symbol(S, Decl(dependentReturnType11.ts, 100, 30)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 100, 12)) + + return param.prop ? 1 : 2; +>param.prop : Symbol(prop, Decl(dependentReturnType11.ts, 95, 20)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 100, 34)) +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 95, 20)) +} + +function g8(param: Type1 & { prop2: Cat | Dog }): Ret { +>g8 : Symbol(g8, Decl(dependentReturnType11.ts, 102, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 104, 12)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 104, 31)) +>Type1 : Symbol(Type1, Decl(dependentReturnType11.ts, 60, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 104, 12)) +>prop2 : Symbol(prop2, Decl(dependentReturnType11.ts, 104, 50)) +>Cat : Symbol(Cat, Decl(dependentReturnType11.ts, 55, 1)) +>Dog : Symbol(Dog, Decl(dependentReturnType11.ts, 51, 1)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 104, 12)) + + return param.prop ? 1 : 2; +>param.prop : Symbol(prop, Decl(dependentReturnType11.ts, 62, 17)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 104, 31)) +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 62, 17)) +} + +function g9([ prop ]: [T]): Ret { // Unsupported. +>g9 : Symbol(g9, Decl(dependentReturnType11.ts, 106, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 108, 12)) +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 108, 32)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 108, 12)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 108, 12)) + + return prop ? 1 : 2; +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 108, 32)) +} + +function g10(param: [T]): Ret { // Unsupported. +>g10 : Symbol(g10, Decl(dependentReturnType11.ts, 110, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 112, 13)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 112, 32)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 112, 13)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 112, 13)) + + return param[0] ? 1 : 2; +>param : Symbol(param, Decl(dependentReturnType11.ts, 112, 32)) +>0 : Symbol(0) +} + +function g11(param: T[]): Ret { // Bad. +>g11 : Symbol(g11, Decl(dependentReturnType11.ts, 114, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 116, 13)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 116, 32)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 116, 13)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 116, 13)) + + return param[0] ? 1 : 2; +>param : Symbol(param, Decl(dependentReturnType11.ts, 116, 32)) +} + +type Type5 = { +>Type5 : Symbol(Type5, Decl(dependentReturnType11.ts, 118, 1)) +>S : Symbol(S, Decl(dependentReturnType11.ts, 120, 11)) + + prop: S, +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 120, 17)) +>S : Symbol(S, Decl(dependentReturnType11.ts, 120, 11)) + + prop2: string[], +>prop2 : Symbol(prop2, Decl(dependentReturnType11.ts, 121, 12)) +} + +function g12(param: Type5): Ret { +>g12 : Symbol(g12, Decl(dependentReturnType11.ts, 123, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 125, 13)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 125, 32)) +>Type5 : Symbol(Type5, Decl(dependentReturnType11.ts, 118, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 125, 13)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 125, 13)) + + return param.prop ? 1 : 2; +>param.prop : Symbol(prop, Decl(dependentReturnType11.ts, 120, 17)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 125, 32)) +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 120, 17)) +} + +type Type6 = { +>Type6 : Symbol(Type6, Decl(dependentReturnType11.ts, 127, 1)) +>S : Symbol(S, Decl(dependentReturnType11.ts, 129, 11)) + + prop: S, +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 129, 17)) +>S : Symbol(S, Decl(dependentReturnType11.ts, 129, 11)) + + prop2: S[], +>prop2 : Symbol(prop2, Decl(dependentReturnType11.ts, 130, 12)) +>S : Symbol(S, Decl(dependentReturnType11.ts, 129, 11)) +} + +function g13(param: Type6): Ret { // Bad. +>g13 : Symbol(g13, Decl(dependentReturnType11.ts, 132, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 134, 13)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 134, 32)) +>Type6 : Symbol(Type6, Decl(dependentReturnType11.ts, 127, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 134, 13)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 134, 13)) + + return param.prop ? 1 : 2; +>param.prop : Symbol(prop, Decl(dependentReturnType11.ts, 129, 17)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 134, 32)) +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 129, 17)) +} + +type Type7 = { +>Type7 : Symbol(Type7, Decl(dependentReturnType11.ts, 136, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 138, 11)) + + [Key in "prop"]: T +>Key : Symbol(Key, Decl(dependentReturnType11.ts, 139, 5)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 138, 11)) +} + +function g14(param: Type7): Ret { // Unsupported. +>g14 : Symbol(g14, Decl(dependentReturnType11.ts, 140, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 142, 13)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 142, 32)) +>Type7 : Symbol(Type7, Decl(dependentReturnType11.ts, 136, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 142, 13)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 142, 13)) + + return param.prop ? 1 : 2; +>param.prop : Symbol(prop) +>param : Symbol(param, Decl(dependentReturnType11.ts, 142, 32)) +>prop : Symbol(prop) +} + +class Class1 { +>Class1 : Symbol(Class1, Decl(dependentReturnType11.ts, 144, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 146, 13)) + + prop!: T; +>prop : Symbol(Class1.prop, Decl(dependentReturnType11.ts, 146, 17)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 146, 13)) +} + +function g15(param: Class1): Ret { // Unsupported. +>g15 : Symbol(g15, Decl(dependentReturnType11.ts, 148, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 150, 13)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 150, 32)) +>Class1 : Symbol(Class1, Decl(dependentReturnType11.ts, 144, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 150, 13)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 150, 13)) + + return param.prop ? 1 : 2; +>param.prop : Symbol(Class1.prop, Decl(dependentReturnType11.ts, 146, 17)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 150, 32)) +>prop : Symbol(Class1.prop, Decl(dependentReturnType11.ts, 146, 17)) +} + +type Type8 = { +>Type8 : Symbol(Type8, Decl(dependentReturnType11.ts, 152, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 154, 11)) + + prop: T, +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 154, 17)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 154, 11)) +} + +type Type9 = { +>Type9 : Symbol(Type9, Decl(dependentReturnType11.ts, 156, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 158, 11)) + + prop2: T, +>prop2 : Symbol(prop2, Decl(dependentReturnType11.ts, 158, 17)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 158, 11)) +} + +function g16(param: Type8["prop2"]>): Ret { // Unsupported. +>g16 : Symbol(g16, Decl(dependentReturnType11.ts, 160, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 162, 13)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 162, 32)) +>Type8 : Symbol(Type8, Decl(dependentReturnType11.ts, 152, 1)) +>Type9 : Symbol(Type9, Decl(dependentReturnType11.ts, 156, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 162, 13)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 162, 13)) + + return param.prop ? 1 : 2; +>param.prop : Symbol(prop, Decl(dependentReturnType11.ts, 154, 17)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 162, 32)) +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 154, 17)) +} + +// Tests for shadowing and resolving the constructed narrowable reference. + +function h1(param: T): Ret { +>h1 : Symbol(h1, Decl(dependentReturnType11.ts, 164, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 168, 12)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 168, 31)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 168, 12)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 168, 12)) + + if (param) { +>param : Symbol(param, Decl(dependentReturnType11.ts, 168, 31)) + + const param = false; +>param : Symbol(param, Decl(dependentReturnType11.ts, 170, 13)) + + return 1; + } + return 2; +} + +function h2({ prop }: { prop: T}): Ret { +>h2 : Symbol(h2, Decl(dependentReturnType11.ts, 174, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 176, 12)) +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 176, 32)) +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 176, 42)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 176, 12)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 176, 12)) + + if (prop) { +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 176, 32)) + + const prop = false; +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 178, 13)) + + return 1; + } + return 2; +} + +function h3(param: { prop: T}): Ret { +>h3 : Symbol(h3, Decl(dependentReturnType11.ts, 182, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 184, 12)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 184, 31)) +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 184, 39)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 184, 12)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 184, 12)) + + if (param.prop) { +>param.prop : Symbol(prop, Decl(dependentReturnType11.ts, 184, 39)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 184, 31)) +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 184, 39)) + + const param = { prop: false }; +>param : Symbol(param, Decl(dependentReturnType11.ts, 186, 13)) +>prop : Symbol(prop, Decl(dependentReturnType11.ts, 186, 23)) + + return 1; + } + return 2; +} + +function h4(param: { "some prop": T }): Ret { +>h4 : Symbol(h4, Decl(dependentReturnType11.ts, 190, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 192, 12)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 192, 31)) +>"some prop" : Symbol("some prop", Decl(dependentReturnType11.ts, 192, 39)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 192, 12)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 192, 12)) + + if (param["some prop"]) { +>param : Symbol(param, Decl(dependentReturnType11.ts, 192, 31)) +>"some prop" : Symbol("some prop", Decl(dependentReturnType11.ts, 192, 39)) + + const param = { "some prop": false }; +>param : Symbol(param, Decl(dependentReturnType11.ts, 194, 13)) +>"some prop" : Symbol("some prop", Decl(dependentReturnType11.ts, 194, 23)) + + return 1; + } + return 2; +} + +function h5(param: T): Ret { +>h5 : Symbol(h5, Decl(dependentReturnType11.ts, 198, 1)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 200, 12)) +>param : Symbol(param, Decl(dependentReturnType11.ts, 200, 31)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 200, 12)) +>Ret : Symbol(Ret, Decl(dependentReturnType11.ts, 0, 0)) +>T : Symbol(T, Decl(dependentReturnType11.ts, 200, 12)) + { + const param = true; +>param : Symbol(param, Decl(dependentReturnType11.ts, 202, 13)) + + if (param) { +>param : Symbol(param, Decl(dependentReturnType11.ts, 202, 13)) + + return 1; // Bad. + } + return 2; + } +} diff --git a/tests/baselines/reference/dependentReturnType11.types b/tests/baselines/reference/dependentReturnType11.types new file mode 100644 index 00000000000..092d9b7191c --- /dev/null +++ b/tests/baselines/reference/dependentReturnType11.types @@ -0,0 +1,831 @@ +//// [tests/cases/compiler/dependentReturnType11.ts] //// + +=== dependentReturnType11.ts === +type Ret = +>Ret : Ret +> : ^^^^^^ + + T extends true ? 1 : +>true : true +> : ^^^^ + + T extends false ? 2 : +>false : false +> : ^^^^^ + + never; + +// Tests for constructing narrowable reference. + +function f1(param: T): Ret { +>f1 : (param: T) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>param : T +> : ^ + + return param ? 1 : 2; +>param ? 1 : 2 : 1 | 2 +> : ^^^^^ +>param : T +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +function f2(param: { prop: T }): Ret { +>f2 : (param: { prop: T; }) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>param : { prop: T; } +> : ^^^^^^^^ ^^^ +>prop : T +> : ^ + + return param.prop ? 1 : 2; +>param.prop ? 1 : 2 : 1 | 2 +> : ^^^^^ +>param.prop : T +> : ^ +>param : { prop: T; } +> : ^^^^^^^^ ^^^ +>prop : T +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +function f3({ prop }: { prop: T }): Ret { +>f3 : ({ prop }: { prop: T; }) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>prop : T +> : ^ +>prop : T +> : ^ + + return prop ? 1 : 2; +>prop ? 1 : 2 : 1 | 2 +> : ^^^^^ +>prop : T +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +function f4({ prop1 }: { prop1: { prop2: T } }): Ret { +>f4 : ({ prop1 }: { prop1: { prop2: T; }; }) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>prop1 : { prop2: T; } +> : ^^^^^^^^^ ^^^ +>prop1 : { prop2: T; } +> : ^^^^^^^^^ ^^^ +>prop2 : T +> : ^ + + return prop1.prop2 ? 1 : 2; +>prop1.prop2 ? 1 : 2 : 1 | 2 +> : ^^^^^ +>prop1.prop2 : T +> : ^ +>prop1 : { prop2: T; } +> : ^^^^^^^^^ ^^^ +>prop2 : T +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +function f5(param: { prop1: { prop2: T } }): Ret { +>f5 : (param: { prop1: { prop2: T; }; }) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>param : { prop1: { prop2: T; }; } +> : ^^^^^^^^^ ^^^ +>prop1 : { prop2: T; } +> : ^^^^^^^^^ ^^^ +>prop2 : T +> : ^ + + return param.prop1.prop2 ? 1 : 2; +>param.prop1.prop2 ? 1 : 2 : 1 | 2 +> : ^^^^^ +>param.prop1.prop2 : T +> : ^ +>param.prop1 : { prop2: T; } +> : ^^^^^^^^^ ^^^ +>param : { prop1: { prop2: T; }; } +> : ^^^^^^^^^ ^^^ +>prop1 : { prop2: T; } +> : ^^^^^^^^^ ^^^ +>prop2 : T +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +function f6({ prop1: { prop2: a } }: { prop1: { prop2: T } }): Ret { +>f6 : ({ prop1: { prop2: a } }: { prop1: { prop2: T; }; }) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>prop1 : any +> : ^^^ +>prop2 : any +> : ^^^ +>a : T +> : ^ +>prop1 : { prop2: T; } +> : ^^^^^^^^^ ^^^ +>prop2 : T +> : ^ + + return a ? 1 : 2; +>a ? 1 : 2 : 1 | 2 +> : ^^^^^ +>a : T +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +function f7({ prop1: { prop2 } }: { prop1: { prop2: T } }): Ret { +>f7 : ({ prop1: { prop2 } }: { prop1: { prop2: T; }; }) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>prop1 : any +> : ^^^ +>prop2 : T +> : ^ +>prop1 : { prop2: T; } +> : ^^^^^^^^^ ^^^ +>prop2 : T +> : ^ + + return prop2 ? 1 : 2; +>prop2 ? 1 : 2 : 1 | 2 +> : ^^^^^ +>prop2 : T +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +function f8({ prop1 }: T): Ret { // Bad. +>f8 : ({ prop1 }: T) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>prop1 : any +> : ^^^ + + return prop1 ? 1 : 2; +>prop1 ? 1 : 2 : 1 | 2 +> : ^^^^^ +>prop1 : any +> : ^^^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +function f9(param: { "some prop": T }): Ret { +>f9 : (param: { "some prop": T; }) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>param : { "some prop": T; } +> : ^^^^^^^^^^^^^^^ ^^^ +>"some prop" : T +> : ^ + + return param["some prop"] ? 1 : 2; +>param["some prop"] ? 1 : 2 : 1 | 2 +> : ^^^^^ +>param["some prop"] : T +> : ^ +>param : { "some prop": T; } +> : ^^^^^^^^^^^^^^^ ^^^ +>"some prop" : "some prop" +> : ^^^^^^^^^^^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +// Tests for detection of valid narrowable type parameter references. + +function g1(param: T): Ret { +>g1 : (param: T) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>param : T +> : ^ + + return param ? 1 : 2; +>param ? 1 : 2 : 1 | 2 +> : ^^^^^ +>param : T +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +function g2(param: { prop: T }): Ret { +>g2 : (param: { prop: T; }) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>param : { prop: T; } +> : ^^^^^^^^ ^^^ +>prop : T +> : ^ + + return param.prop ? 1 : 2; +>param.prop ? 1 : 2 : 1 | 2 +> : ^^^^^ +>param.prop : T +> : ^ +>param : { prop: T; } +> : ^^^^^^^^ ^^^ +>prop : T +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +class Dog { +>Dog : Dog +> : ^^^ + + bark(): void {} +>bark : () => void +> : ^^^^^^ +} + +class Cat { +>Cat : Cat +> : ^^^ + + meow(): void {} +>meow : () => void +> : ^^^^^^ + +} + +type Type1 = { prop: T, prop2: Cat | Dog } +>Type1 : Type1 +> : ^^^^^^^^ +>prop : T +> : ^ +>prop2 : Dog | Cat +> : ^^^^^^^^^ + +function g3(param: Type1): Ret { +>g3 : (param: Type1) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>param : Type1 +> : ^^^^^^^^ + + return param.prop ? 1 : 2; +>param.prop ? 1 : 2 : 1 | 2 +> : ^^^^^ +>param.prop : T +> : ^ +>param : Type1 +> : ^^^^^^^^ +>prop : T +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +type TypeUnused = string; +>TypeUnused : string +> : ^^^^^^ + +function g4(param: Type1, other: TypeUnused): Ret { // Bad. +>g4 : (param: Type1, other: TypeUnused) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ +>param : Type1 +> : ^^^^^^^^ +>other : string +> : ^^^^^^ + + return param.prop ? 1 : 2; +>param.prop ? 1 : 2 : 1 | 2 +> : ^^^^^ +>param.prop : T +> : ^ +>param : Type1 +> : ^^^^^^^^ +>prop : T +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +interface Type2 { + prop: T, +>prop : T +> : ^ + + [s: string]: boolean | undefined, +>s : string +> : ^^^^^^ +} + +function g5(param: Type2): Ret { +>g5 : (param: Type2) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>param : Type2 +> : ^^^^^^^^ + + return param.prop ? 1 : 2; +>param.prop ? 1 : 2 : 1 | 2 +> : ^^^^^ +>param.prop : T +> : ^ +>param : Type2 +> : ^^^^^^^^ +>prop : T +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +interface Type3 { + prop: T, +>prop : T +> : ^ +} + +interface Type3 { + prop2: Cat | Dog, +>prop2 : Dog | Cat +> : ^^^^^^^^^ +} + +function g6(param: Type3): Ret { // Unsupported for now: interface merging. +>g6 : (param: Type3) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>param : Type3 +> : ^^^^^^^^ + + return param.prop ? 1 : 2; +>param.prop ? 1 : 2 : 1 | 2 +> : ^^^^^ +>param.prop : T +> : ^ +>param : Type3 +> : ^^^^^^^^ +>prop : T +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +type Type4 = { +>Type4 : Type4 +> : ^^^^^^^^^^^ + + prop: T, +>prop : T +> : ^ + + prop2: S[], +>prop2 : S[] +> : ^^^ +} + +function g7(param: Type4): Ret { +>g7 : (param: Type4) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^ +>param : Type4 +> : ^^^^^^^^^^^ + + return param.prop ? 1 : 2; +>param.prop ? 1 : 2 : 1 | 2 +> : ^^^^^ +>param.prop : T +> : ^ +>param : Type4 +> : ^^^^^^^^^^^ +>prop : T +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +function g8(param: Type1 & { prop2: Cat | Dog }): Ret { +>g8 : (param: Type1 & { prop2: Cat | Dog; }) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>param : Type1 & { prop2: Cat | Dog; } +> : ^^^^^^^^^^^^^^^^^^^^ ^^^ +>prop2 : Dog | Cat +> : ^^^^^^^^^ + + return param.prop ? 1 : 2; +>param.prop ? 1 : 2 : 1 | 2 +> : ^^^^^ +>param.prop : T +> : ^ +>param : Type1 & { prop2: Cat | Dog; } +> : ^^^^^^^^^^^^^^^^^^^^ ^^^ +>prop : T +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +function g9([ prop ]: [T]): Ret { // Unsupported. +>g9 : ([prop]: [T]) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>prop : T +> : ^ + + return prop ? 1 : 2; +>prop ? 1 : 2 : 1 | 2 +> : ^^^^^ +>prop : T +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +function g10(param: [T]): Ret { // Unsupported. +>g10 : (param: [T]) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>param : [T] +> : ^^^ + + return param[0] ? 1 : 2; +>param[0] ? 1 : 2 : 1 | 2 +> : ^^^^^ +>param[0] : T +> : ^ +>param : [T] +> : ^^^ +>0 : 0 +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +function g11(param: T[]): Ret { // Bad. +>g11 : (param: T[]) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>param : T[] +> : ^^^ + + return param[0] ? 1 : 2; +>param[0] ? 1 : 2 : 1 | 2 +> : ^^^^^ +>param[0] : T +> : ^ +>param : T[] +> : ^^^ +>0 : 0 +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +type Type5 = { +>Type5 : Type5 +> : ^^^^^^^^ + + prop: S, +>prop : S +> : ^ + + prop2: string[], +>prop2 : string[] +> : ^^^^^^^^ +} + +function g12(param: Type5): Ret { +>g12 : (param: Type5) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>param : Type5 +> : ^^^^^^^^ + + return param.prop ? 1 : 2; +>param.prop ? 1 : 2 : 1 | 2 +> : ^^^^^ +>param.prop : T +> : ^ +>param : Type5 +> : ^^^^^^^^ +>prop : T +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +type Type6 = { +>Type6 : Type6 +> : ^^^^^^^^ + + prop: S, +>prop : S +> : ^ + + prop2: S[], +>prop2 : S[] +> : ^^^ +} + +function g13(param: Type6): Ret { // Bad. +>g13 : (param: Type6) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>param : Type6 +> : ^^^^^^^^ + + return param.prop ? 1 : 2; +>param.prop ? 1 : 2 : 1 | 2 +> : ^^^^^ +>param.prop : T +> : ^ +>param : Type6 +> : ^^^^^^^^ +>prop : T +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +type Type7 = { +>Type7 : Type7 +> : ^^^^^^^^ + + [Key in "prop"]: T +} + +function g14(param: Type7): Ret { // Unsupported. +>g14 : (param: Type7) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>param : Type7 +> : ^^^^^^^^ + + return param.prop ? 1 : 2; +>param.prop ? 1 : 2 : 1 | 2 +> : ^^^^^ +>param.prop : T +> : ^ +>param : Type7 +> : ^^^^^^^^ +>prop : T +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +class Class1 { +>Class1 : Class1 +> : ^^^^^^^^^ + + prop!: T; +>prop : T +> : ^ +} + +function g15(param: Class1): Ret { // Unsupported. +>g15 : (param: Class1) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>param : Class1 +> : ^^^^^^^^^ + + return param.prop ? 1 : 2; +>param.prop ? 1 : 2 : 1 | 2 +> : ^^^^^ +>param.prop : T +> : ^ +>param : Class1 +> : ^^^^^^^^^ +>prop : T +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +type Type8 = { +>Type8 : Type8 +> : ^^^^^^^^ + + prop: T, +>prop : T +> : ^ +} + +type Type9 = { +>Type9 : Type9 +> : ^^^^^^^^ + + prop2: T, +>prop2 : T +> : ^ +} + +function g16(param: Type8["prop2"]>): Ret { // Unsupported. +>g16 : (param: Type8["prop2"]>) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>param : Type8 +> : ^^^^^^^^ + + return param.prop ? 1 : 2; +>param.prop ? 1 : 2 : 1 | 2 +> : ^^^^^ +>param.prop : T +> : ^ +>param : Type8 +> : ^^^^^^^^ +>prop : T +> : ^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ +} + +// Tests for shadowing and resolving the constructed narrowable reference. + +function h1(param: T): Ret { +>h1 : (param: T) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>param : T +> : ^ + + if (param) { +>param : T +> : ^ + + const param = false; +>param : false +> : ^^^^^ +>false : false +> : ^^^^^ + + return 1; +>1 : 1 +> : ^ + } + return 2; +>2 : 2 +> : ^ +} + +function h2({ prop }: { prop: T}): Ret { +>h2 : ({ prop }: { prop: T; }) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>prop : T +> : ^ +>prop : T +> : ^ + + if (prop) { +>prop : T +> : ^ + + const prop = false; +>prop : false +> : ^^^^^ +>false : false +> : ^^^^^ + + return 1; +>1 : 1 +> : ^ + } + return 2; +>2 : 2 +> : ^ +} + +function h3(param: { prop: T}): Ret { +>h3 : (param: { prop: T; }) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>param : { prop: T; } +> : ^^^^^^^^ ^^^ +>prop : T +> : ^ + + if (param.prop) { +>param.prop : T +> : ^ +>param : { prop: T; } +> : ^^^^^^^^ ^^^ +>prop : T +> : ^ + + const param = { prop: false }; +>param : { prop: boolean; } +> : ^^^^^^^^^^^^^^^^^^ +>{ prop: false } : { prop: boolean; } +> : ^^^^^^^^^^^^^^^^^^ +>prop : boolean +> : ^^^^^^^ +>false : false +> : ^^^^^ + + return 1; +>1 : 1 +> : ^ + } + return 2; +>2 : 2 +> : ^ +} + +function h4(param: { "some prop": T }): Ret { +>h4 : (param: { "some prop": T; }) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>param : { "some prop": T; } +> : ^^^^^^^^^^^^^^^ ^^^ +>"some prop" : T +> : ^ + + if (param["some prop"]) { +>param["some prop"] : T +> : ^ +>param : { "some prop": T; } +> : ^^^^^^^^^^^^^^^ ^^^ +>"some prop" : "some prop" +> : ^^^^^^^^^^^ + + const param = { "some prop": false }; +>param : { "some prop": boolean; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ "some prop": false } : { "some prop": boolean; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>"some prop" : boolean +> : ^^^^^^^ +>false : false +> : ^^^^^ + + return 1; +>1 : 1 +> : ^ + } + return 2; +>2 : 2 +> : ^ +} + +function h5(param: T): Ret { +>h5 : (param: T) => Ret +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>param : T +> : ^ + { + const param = true; +>param : true +> : ^^^^ +>true : true +> : ^^^^ + + if (param) { +>param : true +> : ^^^^ + + return 1; // Bad. +>1 : 1 +> : ^ + } + return 2; +>2 : 2 +> : ^ + } +} diff --git a/tests/cases/compiler/dependentReturnType11.ts b/tests/cases/compiler/dependentReturnType11.ts new file mode 100644 index 00000000000..82da828ed17 --- /dev/null +++ b/tests/cases/compiler/dependentReturnType11.ts @@ -0,0 +1,212 @@ +// @noEmit: true +// @strict: true + +type Ret = + T extends true ? 1 : + T extends false ? 2 : + never; + +// Tests for constructing narrowable reference. + +function f1(param: T): Ret { + return param ? 1 : 2; +} + +function f2(param: { prop: T }): Ret { + return param.prop ? 1 : 2; +} + +function f3({ prop }: { prop: T }): Ret { + return prop ? 1 : 2; +} + +function f4({ prop1 }: { prop1: { prop2: T } }): Ret { + return prop1.prop2 ? 1 : 2; +} + +function f5(param: { prop1: { prop2: T } }): Ret { + return param.prop1.prop2 ? 1 : 2; +} + +function f6({ prop1: { prop2: a } }: { prop1: { prop2: T } }): Ret { + return a ? 1 : 2; +} + +function f7({ prop1: { prop2 } }: { prop1: { prop2: T } }): Ret { + return prop2 ? 1 : 2; +} + +function f8({ prop1 }: T): Ret { // Bad. + return prop1 ? 1 : 2; +} + +function f9(param: { "some prop": T }): Ret { + return param["some prop"] ? 1 : 2; +} + +// Tests for detection of valid narrowable type parameter references. + +function g1(param: T): Ret { + return param ? 1 : 2; +} + +function g2(param: { prop: T }): Ret { + return param.prop ? 1 : 2; +} + +class Dog { + bark(): void {} +} + +class Cat { + meow(): void {} + +} + +type Type1 = { prop: T, prop2: Cat | Dog } + +function g3(param: Type1): Ret { + return param.prop ? 1 : 2; +} + +type TypeUnused = string; + +function g4(param: Type1, other: TypeUnused): Ret { // Bad. + return param.prop ? 1 : 2; +} + +interface Type2 { + prop: T, + [s: string]: boolean | undefined, +} + +function g5(param: Type2): Ret { + return param.prop ? 1 : 2; +} + +interface Type3 { + prop: T, +} + +interface Type3 { + prop2: Cat | Dog, +} + +function g6(param: Type3): Ret { // Unsupported for now: interface merging. + return param.prop ? 1 : 2; +} + +type Type4 = { + prop: T, + prop2: S[], +} + +function g7(param: Type4): Ret { + return param.prop ? 1 : 2; +} + +function g8(param: Type1 & { prop2: Cat | Dog }): Ret { + return param.prop ? 1 : 2; +} + +function g9([ prop ]: [T]): Ret { // Unsupported. + return prop ? 1 : 2; +} + +function g10(param: [T]): Ret { // Unsupported. + return param[0] ? 1 : 2; +} + +function g11(param: T[]): Ret { // Bad. + return param[0] ? 1 : 2; +} + +type Type5 = { + prop: S, + prop2: string[], +} + +function g12(param: Type5): Ret { + return param.prop ? 1 : 2; +} + +type Type6 = { + prop: S, + prop2: S[], +} + +function g13(param: Type6): Ret { // Bad. + return param.prop ? 1 : 2; +} + +type Type7 = { + [Key in "prop"]: T +} + +function g14(param: Type7): Ret { // Unsupported. + return param.prop ? 1 : 2; +} + +class Class1 { + prop!: T; +} + +function g15(param: Class1): Ret { // Unsupported. + return param.prop ? 1 : 2; +} + +type Type8 = { + prop: T, +} + +type Type9 = { + prop2: T, +} + +function g16(param: Type8["prop2"]>): Ret { // Unsupported. + return param.prop ? 1 : 2; +} + +// Tests for shadowing and resolving the constructed narrowable reference. + +function h1(param: T): Ret { + if (param) { + const param = false; + return 1; + } + return 2; +} + +function h2({ prop }: { prop: T}): Ret { + if (prop) { + const prop = false; + return 1; + } + return 2; +} + +function h3(param: { prop: T}): Ret { + if (param.prop) { + const param = { prop: false }; + return 1; + } + return 2; +} + +function h4(param: { "some prop": T }): Ret { + if (param["some prop"]) { + const param = { "some prop": false }; + return 1; + } + return 2; +} + +function h5(param: T): Ret { + { + const param = true; + if (param) { + return 1; // Bad. + } + return 2; + } +} \ No newline at end of file