mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Detect and construct narrowable references for embedded type parameters
This commit is contained in:
+88
-23
@@ -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<T, T, ...>`
|
||||
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<T, T, ...>`
|
||||
const typeArg = typeArgsReferencingT[0];
|
||||
if (!(typeArg.kind & SyntaxKind.TypeReference)) return false; // e.g. `Foo<Wrapper<T>, ...>`
|
||||
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:
|
||||
|
||||
@@ -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<T>'.
|
||||
dependentReturnType11.ts(37,24): error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
dependentReturnType11.ts(72,25): error TS2322: Type '1' is not assignable to type 'Ret<T>'.
|
||||
dependentReturnType11.ts(72,29): error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
dependentReturnType11.ts(93,25): error TS2322: Type '1' is not assignable to type 'Ret<T>'.
|
||||
dependentReturnType11.ts(93,29): error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
dependentReturnType11.ts(110,19): error TS2322: Type '1' is not assignable to type 'Ret<T>'.
|
||||
dependentReturnType11.ts(110,23): error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
dependentReturnType11.ts(114,23): error TS2322: Type '1' is not assignable to type 'Ret<T>'.
|
||||
dependentReturnType11.ts(114,27): error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
dependentReturnType11.ts(118,23): error TS2322: Type '1' is not assignable to type 'Ret<T>'.
|
||||
dependentReturnType11.ts(118,27): error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
dependentReturnType11.ts(136,25): error TS2322: Type '1' is not assignable to type 'Ret<T>'.
|
||||
dependentReturnType11.ts(136,29): error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
dependentReturnType11.ts(144,25): error TS2322: Type '1' is not assignable to type 'Ret<T>'.
|
||||
dependentReturnType11.ts(144,29): error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
dependentReturnType11.ts(152,25): error TS2322: Type '1' is not assignable to type 'Ret<T>'.
|
||||
dependentReturnType11.ts(152,29): error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
dependentReturnType11.ts(205,13): error TS2322: Type '1' is not assignable to type 'Ret<T>'.
|
||||
dependentReturnType11.ts(207,9): error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
|
||||
|
||||
==== dependentReturnType11.ts (21 errors) ====
|
||||
type Ret<T extends boolean> =
|
||||
T extends true ? 1 :
|
||||
T extends false ? 2 :
|
||||
never;
|
||||
|
||||
// Tests for constructing narrowable reference.
|
||||
|
||||
function f1<T extends boolean>(param: T): Ret<T> {
|
||||
return param ? 1 : 2;
|
||||
}
|
||||
|
||||
function f2<T extends boolean>(param: { prop: T }): Ret<T> {
|
||||
return param.prop ? 1 : 2;
|
||||
}
|
||||
|
||||
function f3<T extends boolean>({ prop }: { prop: T }): Ret<T> {
|
||||
return prop ? 1 : 2;
|
||||
}
|
||||
|
||||
function f4<T extends boolean>({ prop1 }: { prop1: { prop2: T } }): Ret<T> {
|
||||
return prop1.prop2 ? 1 : 2;
|
||||
}
|
||||
|
||||
function f5<T extends boolean>(param: { prop1: { prop2: T } }): Ret<T> {
|
||||
return param.prop1.prop2 ? 1 : 2;
|
||||
}
|
||||
|
||||
function f6<T extends boolean>({ prop1: { prop2: a } }: { prop1: { prop2: T } }): Ret<T> {
|
||||
return a ? 1 : 2;
|
||||
}
|
||||
|
||||
function f7<T extends boolean>({ prop1: { prop2 } }: { prop1: { prop2: T } }): Ret<T> {
|
||||
return prop2 ? 1 : 2;
|
||||
}
|
||||
|
||||
function f8<T extends boolean>({ prop1 }: T): Ret<T> { // 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<T>'.
|
||||
~
|
||||
!!! error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
}
|
||||
|
||||
function f9<T extends boolean>(param: { "some prop": T }): Ret<T> {
|
||||
return param["some prop"] ? 1 : 2;
|
||||
}
|
||||
|
||||
// Tests for detection of valid narrowable type parameter references.
|
||||
|
||||
function g1<T extends boolean>(param: T): Ret<T> {
|
||||
return param ? 1 : 2;
|
||||
}
|
||||
|
||||
function g2<T extends boolean>(param: { prop: T }): Ret<T> {
|
||||
return param.prop ? 1 : 2;
|
||||
}
|
||||
|
||||
class Dog {
|
||||
bark(): void {}
|
||||
}
|
||||
|
||||
class Cat {
|
||||
meow(): void {}
|
||||
|
||||
}
|
||||
|
||||
type Type1<T> = { prop: T, prop2: Cat | Dog }
|
||||
|
||||
function g3<T extends boolean>(param: Type1<T>): Ret<T> {
|
||||
return param.prop ? 1 : 2;
|
||||
}
|
||||
|
||||
type TypeUnused<T> = string;
|
||||
|
||||
function g4<T extends boolean>(param: Type1<T>, other: TypeUnused<T>): Ret<T> { // Bad.
|
||||
return param.prop ? 1 : 2;
|
||||
~
|
||||
!!! error TS2322: Type '1' is not assignable to type 'Ret<T>'.
|
||||
~
|
||||
!!! error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
}
|
||||
|
||||
interface Type2<T extends boolean> {
|
||||
prop: T,
|
||||
[s: string]: boolean | undefined,
|
||||
}
|
||||
|
||||
function g5<T extends boolean>(param: Type2<T>): Ret<T> {
|
||||
return param.prop ? 1 : 2;
|
||||
}
|
||||
|
||||
interface Type3<T extends boolean> {
|
||||
prop: T,
|
||||
}
|
||||
|
||||
interface Type3<T extends boolean> {
|
||||
prop2: Cat | Dog,
|
||||
}
|
||||
|
||||
function g6<T extends boolean>(param: Type3<T>): Ret<T> { // Unsupported for now: interface merging.
|
||||
return param.prop ? 1 : 2;
|
||||
~
|
||||
!!! error TS2322: Type '1' is not assignable to type 'Ret<T>'.
|
||||
~
|
||||
!!! error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
}
|
||||
|
||||
type Type4<T, S> = {
|
||||
prop: T,
|
||||
prop2: S[],
|
||||
}
|
||||
|
||||
function g7<T extends boolean, S>(param: Type4<T, S>): Ret<T> {
|
||||
return param.prop ? 1 : 2;
|
||||
}
|
||||
|
||||
function g8<T extends boolean>(param: Type1<T> & { prop2: Cat | Dog }): Ret<T> {
|
||||
return param.prop ? 1 : 2;
|
||||
}
|
||||
|
||||
function g9<T extends boolean>([ prop ]: [T]): Ret<T> { // Unsupported.
|
||||
return prop ? 1 : 2;
|
||||
~
|
||||
!!! error TS2322: Type '1' is not assignable to type 'Ret<T>'.
|
||||
~
|
||||
!!! error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
}
|
||||
|
||||
function g10<T extends boolean>(param: [T]): Ret<T> { // Unsupported.
|
||||
return param[0] ? 1 : 2;
|
||||
~
|
||||
!!! error TS2322: Type '1' is not assignable to type 'Ret<T>'.
|
||||
~
|
||||
!!! error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
}
|
||||
|
||||
function g11<T extends boolean>(param: T[]): Ret<T> { // Bad.
|
||||
return param[0] ? 1 : 2;
|
||||
~
|
||||
!!! error TS2322: Type '1' is not assignable to type 'Ret<T>'.
|
||||
~
|
||||
!!! error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
}
|
||||
|
||||
type Type5<S> = {
|
||||
prop: S,
|
||||
prop2: string[],
|
||||
}
|
||||
|
||||
function g12<T extends boolean>(param: Type5<T>): Ret<T> {
|
||||
return param.prop ? 1 : 2;
|
||||
}
|
||||
|
||||
type Type6<S> = {
|
||||
prop: S,
|
||||
prop2: S[],
|
||||
}
|
||||
|
||||
function g13<T extends boolean>(param: Type6<T>): Ret<T> { // Bad.
|
||||
return param.prop ? 1 : 2;
|
||||
~
|
||||
!!! error TS2322: Type '1' is not assignable to type 'Ret<T>'.
|
||||
~
|
||||
!!! error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
}
|
||||
|
||||
type Type7<T> = {
|
||||
[Key in "prop"]: T
|
||||
}
|
||||
|
||||
function g14<T extends boolean>(param: Type7<T>): Ret<T> { // Unsupported.
|
||||
return param.prop ? 1 : 2;
|
||||
~
|
||||
!!! error TS2322: Type '1' is not assignable to type 'Ret<T>'.
|
||||
~
|
||||
!!! error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
}
|
||||
|
||||
class Class1<T> {
|
||||
prop!: T;
|
||||
}
|
||||
|
||||
function g15<T extends boolean>(param: Class1<T>): Ret<T> { // Unsupported.
|
||||
return param.prop ? 1 : 2;
|
||||
~
|
||||
!!! error TS2322: Type '1' is not assignable to type 'Ret<T>'.
|
||||
~
|
||||
!!! error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
}
|
||||
|
||||
type Type8<T> = {
|
||||
prop: T,
|
||||
}
|
||||
|
||||
type Type9<T> = {
|
||||
prop2: T,
|
||||
}
|
||||
|
||||
function g16<T extends boolean>(param: Type8<Type9<T>["prop2"]>): Ret<T> { // Unsupported.
|
||||
return param.prop ? 1 : 2;
|
||||
}
|
||||
|
||||
// Tests for shadowing and resolving the constructed narrowable reference.
|
||||
|
||||
function h1<T extends boolean>(param: T): Ret<T> {
|
||||
if (param) {
|
||||
const param = false;
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function h2<T extends boolean>({ prop }: { prop: T}): Ret<T> {
|
||||
if (prop) {
|
||||
const prop = false;
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function h3<T extends boolean>(param: { prop: T}): Ret<T> {
|
||||
if (param.prop) {
|
||||
const param = { prop: false };
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function h4<T extends boolean>(param: { "some prop": T }): Ret<T> {
|
||||
if (param["some prop"]) {
|
||||
const param = { "some prop": false };
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function h5<T extends boolean>(param: T): Ret<T> {
|
||||
{
|
||||
const param = true;
|
||||
if (param) {
|
||||
return 1; // Bad.
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '1' is not assignable to type 'Ret<T>'.
|
||||
}
|
||||
return 2;
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,627 @@
|
||||
//// [tests/cases/compiler/dependentReturnType11.ts] ////
|
||||
|
||||
=== dependentReturnType11.ts ===
|
||||
type Ret<T extends boolean> =
|
||||
>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<T extends boolean>(param: T): Ret<T> {
|
||||
>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<T extends boolean>(param: { prop: T }): Ret<T> {
|
||||
>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<T extends boolean>({ prop }: { prop: T }): Ret<T> {
|
||||
>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<T extends boolean>({ prop1 }: { prop1: { prop2: T } }): Ret<T> {
|
||||
>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<T extends boolean>(param: { prop1: { prop2: T } }): Ret<T> {
|
||||
>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<T extends boolean>({ prop1: { prop2: a } }: { prop1: { prop2: T } }): Ret<T> {
|
||||
>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<T extends boolean>({ prop1: { prop2 } }: { prop1: { prop2: T } }): Ret<T> {
|
||||
>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<T extends boolean>({ prop1 }: T): Ret<T> { // 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<T extends boolean>(param: { "some prop": T }): Ret<T> {
|
||||
>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<T extends boolean>(param: T): Ret<T> {
|
||||
>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<T extends boolean>(param: { prop: T }): Ret<T> {
|
||||
>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<T> = { 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<T extends boolean>(param: Type1<T>): Ret<T> {
|
||||
>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<T> = string;
|
||||
>TypeUnused : Symbol(TypeUnused, Decl(dependentReturnType11.ts, 66, 1))
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 68, 16))
|
||||
|
||||
function g4<T extends boolean>(param: Type1<T>, other: TypeUnused<T>): Ret<T> { // 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<T extends boolean> {
|
||||
>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<T extends boolean>(param: Type2<T>): Ret<T> {
|
||||
>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<T extends boolean> {
|
||||
>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<T extends boolean> {
|
||||
>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<T extends boolean>(param: Type3<T>): Ret<T> { // 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<T, S> = {
|
||||
>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<T extends boolean, S>(param: Type4<T, S>): Ret<T> {
|
||||
>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<T extends boolean>(param: Type1<T> & { prop2: Cat | Dog }): Ret<T> {
|
||||
>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<T extends boolean>([ prop ]: [T]): Ret<T> { // 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<T extends boolean>(param: [T]): Ret<T> { // 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<T extends boolean>(param: T[]): Ret<T> { // 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<S> = {
|
||||
>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<T extends boolean>(param: Type5<T>): Ret<T> {
|
||||
>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<S> = {
|
||||
>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<T extends boolean>(param: Type6<T>): Ret<T> { // 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<T> = {
|
||||
>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<T extends boolean>(param: Type7<T>): Ret<T> { // 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<T> {
|
||||
>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<T extends boolean>(param: Class1<T>): Ret<T> { // 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<T> = {
|
||||
>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<T> = {
|
||||
>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<T extends boolean>(param: Type8<Type9<T>["prop2"]>): Ret<T> { // 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<T extends boolean>(param: T): Ret<T> {
|
||||
>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<T extends boolean>({ prop }: { prop: T}): Ret<T> {
|
||||
>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<T extends boolean>(param: { prop: T}): Ret<T> {
|
||||
>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<T extends boolean>(param: { "some prop": T }): Ret<T> {
|
||||
>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<T extends boolean>(param: T): Ret<T> {
|
||||
>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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,831 @@
|
||||
//// [tests/cases/compiler/dependentReturnType11.ts] ////
|
||||
|
||||
=== dependentReturnType11.ts ===
|
||||
type Ret<T extends boolean> =
|
||||
>Ret : Ret<T>
|
||||
> : ^^^^^^
|
||||
|
||||
T extends true ? 1 :
|
||||
>true : true
|
||||
> : ^^^^
|
||||
|
||||
T extends false ? 2 :
|
||||
>false : false
|
||||
> : ^^^^^
|
||||
|
||||
never;
|
||||
|
||||
// Tests for constructing narrowable reference.
|
||||
|
||||
function f1<T extends boolean>(param: T): Ret<T> {
|
||||
>f1 : <T extends boolean>(param: T) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>param : T
|
||||
> : ^
|
||||
|
||||
return param ? 1 : 2;
|
||||
>param ? 1 : 2 : 1 | 2
|
||||
> : ^^^^^
|
||||
>param : T
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
function f2<T extends boolean>(param: { prop: T }): Ret<T> {
|
||||
>f2 : <T extends boolean>(param: { prop: T; }) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>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<T extends boolean>({ prop }: { prop: T }): Ret<T> {
|
||||
>f3 : <T extends boolean>({ prop }: { prop: T; }) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
>prop : T
|
||||
> : ^
|
||||
|
||||
return prop ? 1 : 2;
|
||||
>prop ? 1 : 2 : 1 | 2
|
||||
> : ^^^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
function f4<T extends boolean>({ prop1 }: { prop1: { prop2: T } }): Ret<T> {
|
||||
>f4 : <T extends boolean>({ prop1 }: { prop1: { prop2: T; }; }) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>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<T extends boolean>(param: { prop1: { prop2: T } }): Ret<T> {
|
||||
>f5 : <T extends boolean>(param: { prop1: { prop2: T; }; }) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>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<T extends boolean>({ prop1: { prop2: a } }: { prop1: { prop2: T } }): Ret<T> {
|
||||
>f6 : <T extends boolean>({ prop1: { prop2: a } }: { prop1: { prop2: T; }; }) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>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<T extends boolean>({ prop1: { prop2 } }: { prop1: { prop2: T } }): Ret<T> {
|
||||
>f7 : <T extends boolean>({ prop1: { prop2 } }: { prop1: { prop2: T; }; }) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>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<T extends boolean>({ prop1 }: T): Ret<T> { // Bad.
|
||||
>f8 : <T extends boolean>({ prop1 }: T) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>prop1 : any
|
||||
> : ^^^
|
||||
|
||||
return prop1 ? 1 : 2;
|
||||
>prop1 ? 1 : 2 : 1 | 2
|
||||
> : ^^^^^
|
||||
>prop1 : any
|
||||
> : ^^^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
function f9<T extends boolean>(param: { "some prop": T }): Ret<T> {
|
||||
>f9 : <T extends boolean>(param: { "some prop": T; }) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>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<T extends boolean>(param: T): Ret<T> {
|
||||
>g1 : <T extends boolean>(param: T) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>param : T
|
||||
> : ^
|
||||
|
||||
return param ? 1 : 2;
|
||||
>param ? 1 : 2 : 1 | 2
|
||||
> : ^^^^^
|
||||
>param : T
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
function g2<T extends boolean>(param: { prop: T }): Ret<T> {
|
||||
>g2 : <T extends boolean>(param: { prop: T; }) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>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<T> = { prop: T, prop2: Cat | Dog }
|
||||
>Type1 : Type1<T>
|
||||
> : ^^^^^^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
>prop2 : Dog | Cat
|
||||
> : ^^^^^^^^^
|
||||
|
||||
function g3<T extends boolean>(param: Type1<T>): Ret<T> {
|
||||
>g3 : <T extends boolean>(param: Type1<T>) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>param : Type1<T>
|
||||
> : ^^^^^^^^
|
||||
|
||||
return param.prop ? 1 : 2;
|
||||
>param.prop ? 1 : 2 : 1 | 2
|
||||
> : ^^^^^
|
||||
>param.prop : T
|
||||
> : ^
|
||||
>param : Type1<T>
|
||||
> : ^^^^^^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
type TypeUnused<T> = string;
|
||||
>TypeUnused : string
|
||||
> : ^^^^^^
|
||||
|
||||
function g4<T extends boolean>(param: Type1<T>, other: TypeUnused<T>): Ret<T> { // Bad.
|
||||
>g4 : <T extends boolean>(param: Type1<T>, other: TypeUnused<T>) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^
|
||||
>param : Type1<T>
|
||||
> : ^^^^^^^^
|
||||
>other : string
|
||||
> : ^^^^^^
|
||||
|
||||
return param.prop ? 1 : 2;
|
||||
>param.prop ? 1 : 2 : 1 | 2
|
||||
> : ^^^^^
|
||||
>param.prop : T
|
||||
> : ^
|
||||
>param : Type1<T>
|
||||
> : ^^^^^^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
interface Type2<T extends boolean> {
|
||||
prop: T,
|
||||
>prop : T
|
||||
> : ^
|
||||
|
||||
[s: string]: boolean | undefined,
|
||||
>s : string
|
||||
> : ^^^^^^
|
||||
}
|
||||
|
||||
function g5<T extends boolean>(param: Type2<T>): Ret<T> {
|
||||
>g5 : <T extends boolean>(param: Type2<T>) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>param : Type2<T>
|
||||
> : ^^^^^^^^
|
||||
|
||||
return param.prop ? 1 : 2;
|
||||
>param.prop ? 1 : 2 : 1 | 2
|
||||
> : ^^^^^
|
||||
>param.prop : T
|
||||
> : ^
|
||||
>param : Type2<T>
|
||||
> : ^^^^^^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
interface Type3<T extends boolean> {
|
||||
prop: T,
|
||||
>prop : T
|
||||
> : ^
|
||||
}
|
||||
|
||||
interface Type3<T extends boolean> {
|
||||
prop2: Cat | Dog,
|
||||
>prop2 : Dog | Cat
|
||||
> : ^^^^^^^^^
|
||||
}
|
||||
|
||||
function g6<T extends boolean>(param: Type3<T>): Ret<T> { // Unsupported for now: interface merging.
|
||||
>g6 : <T extends boolean>(param: Type3<T>) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>param : Type3<T>
|
||||
> : ^^^^^^^^
|
||||
|
||||
return param.prop ? 1 : 2;
|
||||
>param.prop ? 1 : 2 : 1 | 2
|
||||
> : ^^^^^
|
||||
>param.prop : T
|
||||
> : ^
|
||||
>param : Type3<T>
|
||||
> : ^^^^^^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
type Type4<T, S> = {
|
||||
>Type4 : Type4<T, S>
|
||||
> : ^^^^^^^^^^^
|
||||
|
||||
prop: T,
|
||||
>prop : T
|
||||
> : ^
|
||||
|
||||
prop2: S[],
|
||||
>prop2 : S[]
|
||||
> : ^^^
|
||||
}
|
||||
|
||||
function g7<T extends boolean, S>(param: Type4<T, S>): Ret<T> {
|
||||
>g7 : <T extends boolean, S>(param: Type4<T, S>) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^
|
||||
>param : Type4<T, S>
|
||||
> : ^^^^^^^^^^^
|
||||
|
||||
return param.prop ? 1 : 2;
|
||||
>param.prop ? 1 : 2 : 1 | 2
|
||||
> : ^^^^^
|
||||
>param.prop : T
|
||||
> : ^
|
||||
>param : Type4<T, S>
|
||||
> : ^^^^^^^^^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
function g8<T extends boolean>(param: Type1<T> & { prop2: Cat | Dog }): Ret<T> {
|
||||
>g8 : <T extends boolean>(param: Type1<T> & { prop2: Cat | Dog; }) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>param : Type1<T> & { prop2: Cat | Dog; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^ ^^^
|
||||
>prop2 : Dog | Cat
|
||||
> : ^^^^^^^^^
|
||||
|
||||
return param.prop ? 1 : 2;
|
||||
>param.prop ? 1 : 2 : 1 | 2
|
||||
> : ^^^^^
|
||||
>param.prop : T
|
||||
> : ^
|
||||
>param : Type1<T> & { prop2: Cat | Dog; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^ ^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
function g9<T extends boolean>([ prop ]: [T]): Ret<T> { // Unsupported.
|
||||
>g9 : <T extends boolean>([prop]: [T]) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
|
||||
return prop ? 1 : 2;
|
||||
>prop ? 1 : 2 : 1 | 2
|
||||
> : ^^^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
function g10<T extends boolean>(param: [T]): Ret<T> { // Unsupported.
|
||||
>g10 : <T extends boolean>(param: [T]) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>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<T extends boolean>(param: T[]): Ret<T> { // Bad.
|
||||
>g11 : <T extends boolean>(param: T[]) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>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<S> = {
|
||||
>Type5 : Type5<S>
|
||||
> : ^^^^^^^^
|
||||
|
||||
prop: S,
|
||||
>prop : S
|
||||
> : ^
|
||||
|
||||
prop2: string[],
|
||||
>prop2 : string[]
|
||||
> : ^^^^^^^^
|
||||
}
|
||||
|
||||
function g12<T extends boolean>(param: Type5<T>): Ret<T> {
|
||||
>g12 : <T extends boolean>(param: Type5<T>) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>param : Type5<T>
|
||||
> : ^^^^^^^^
|
||||
|
||||
return param.prop ? 1 : 2;
|
||||
>param.prop ? 1 : 2 : 1 | 2
|
||||
> : ^^^^^
|
||||
>param.prop : T
|
||||
> : ^
|
||||
>param : Type5<T>
|
||||
> : ^^^^^^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
type Type6<S> = {
|
||||
>Type6 : Type6<S>
|
||||
> : ^^^^^^^^
|
||||
|
||||
prop: S,
|
||||
>prop : S
|
||||
> : ^
|
||||
|
||||
prop2: S[],
|
||||
>prop2 : S[]
|
||||
> : ^^^
|
||||
}
|
||||
|
||||
function g13<T extends boolean>(param: Type6<T>): Ret<T> { // Bad.
|
||||
>g13 : <T extends boolean>(param: Type6<T>) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>param : Type6<T>
|
||||
> : ^^^^^^^^
|
||||
|
||||
return param.prop ? 1 : 2;
|
||||
>param.prop ? 1 : 2 : 1 | 2
|
||||
> : ^^^^^
|
||||
>param.prop : T
|
||||
> : ^
|
||||
>param : Type6<T>
|
||||
> : ^^^^^^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
type Type7<T> = {
|
||||
>Type7 : Type7<T>
|
||||
> : ^^^^^^^^
|
||||
|
||||
[Key in "prop"]: T
|
||||
}
|
||||
|
||||
function g14<T extends boolean>(param: Type7<T>): Ret<T> { // Unsupported.
|
||||
>g14 : <T extends boolean>(param: Type7<T>) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>param : Type7<T>
|
||||
> : ^^^^^^^^
|
||||
|
||||
return param.prop ? 1 : 2;
|
||||
>param.prop ? 1 : 2 : 1 | 2
|
||||
> : ^^^^^
|
||||
>param.prop : T
|
||||
> : ^
|
||||
>param : Type7<T>
|
||||
> : ^^^^^^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
class Class1<T> {
|
||||
>Class1 : Class1<T>
|
||||
> : ^^^^^^^^^
|
||||
|
||||
prop!: T;
|
||||
>prop : T
|
||||
> : ^
|
||||
}
|
||||
|
||||
function g15<T extends boolean>(param: Class1<T>): Ret<T> { // Unsupported.
|
||||
>g15 : <T extends boolean>(param: Class1<T>) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>param : Class1<T>
|
||||
> : ^^^^^^^^^
|
||||
|
||||
return param.prop ? 1 : 2;
|
||||
>param.prop ? 1 : 2 : 1 | 2
|
||||
> : ^^^^^
|
||||
>param.prop : T
|
||||
> : ^
|
||||
>param : Class1<T>
|
||||
> : ^^^^^^^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
type Type8<T> = {
|
||||
>Type8 : Type8<T>
|
||||
> : ^^^^^^^^
|
||||
|
||||
prop: T,
|
||||
>prop : T
|
||||
> : ^
|
||||
}
|
||||
|
||||
type Type9<T> = {
|
||||
>Type9 : Type9<T>
|
||||
> : ^^^^^^^^
|
||||
|
||||
prop2: T,
|
||||
>prop2 : T
|
||||
> : ^
|
||||
}
|
||||
|
||||
function g16<T extends boolean>(param: Type8<Type9<T>["prop2"]>): Ret<T> { // Unsupported.
|
||||
>g16 : <T extends boolean>(param: Type8<Type9<T>["prop2"]>) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>param : Type8<T>
|
||||
> : ^^^^^^^^
|
||||
|
||||
return param.prop ? 1 : 2;
|
||||
>param.prop ? 1 : 2 : 1 | 2
|
||||
> : ^^^^^
|
||||
>param.prop : T
|
||||
> : ^
|
||||
>param : Type8<T>
|
||||
> : ^^^^^^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
// Tests for shadowing and resolving the constructed narrowable reference.
|
||||
|
||||
function h1<T extends boolean>(param: T): Ret<T> {
|
||||
>h1 : <T extends boolean>(param: T) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>param : T
|
||||
> : ^
|
||||
|
||||
if (param) {
|
||||
>param : T
|
||||
> : ^
|
||||
|
||||
const param = false;
|
||||
>param : false
|
||||
> : ^^^^^
|
||||
>false : false
|
||||
> : ^^^^^
|
||||
|
||||
return 1;
|
||||
>1 : 1
|
||||
> : ^
|
||||
}
|
||||
return 2;
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
function h2<T extends boolean>({ prop }: { prop: T}): Ret<T> {
|
||||
>h2 : <T extends boolean>({ prop }: { prop: T; }) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>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<T extends boolean>(param: { prop: T}): Ret<T> {
|
||||
>h3 : <T extends boolean>(param: { prop: T; }) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>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<T extends boolean>(param: { "some prop": T }): Ret<T> {
|
||||
>h4 : <T extends boolean>(param: { "some prop": T; }) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>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<T extends boolean>(param: T): Ret<T> {
|
||||
>h5 : <T extends boolean>(param: T) => Ret<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>param : T
|
||||
> : ^
|
||||
{
|
||||
const param = true;
|
||||
>param : true
|
||||
> : ^^^^
|
||||
>true : true
|
||||
> : ^^^^
|
||||
|
||||
if (param) {
|
||||
>param : true
|
||||
> : ^^^^
|
||||
|
||||
return 1; // Bad.
|
||||
>1 : 1
|
||||
> : ^
|
||||
}
|
||||
return 2;
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
// @noEmit: true
|
||||
// @strict: true
|
||||
|
||||
type Ret<T extends boolean> =
|
||||
T extends true ? 1 :
|
||||
T extends false ? 2 :
|
||||
never;
|
||||
|
||||
// Tests for constructing narrowable reference.
|
||||
|
||||
function f1<T extends boolean>(param: T): Ret<T> {
|
||||
return param ? 1 : 2;
|
||||
}
|
||||
|
||||
function f2<T extends boolean>(param: { prop: T }): Ret<T> {
|
||||
return param.prop ? 1 : 2;
|
||||
}
|
||||
|
||||
function f3<T extends boolean>({ prop }: { prop: T }): Ret<T> {
|
||||
return prop ? 1 : 2;
|
||||
}
|
||||
|
||||
function f4<T extends boolean>({ prop1 }: { prop1: { prop2: T } }): Ret<T> {
|
||||
return prop1.prop2 ? 1 : 2;
|
||||
}
|
||||
|
||||
function f5<T extends boolean>(param: { prop1: { prop2: T } }): Ret<T> {
|
||||
return param.prop1.prop2 ? 1 : 2;
|
||||
}
|
||||
|
||||
function f6<T extends boolean>({ prop1: { prop2: a } }: { prop1: { prop2: T } }): Ret<T> {
|
||||
return a ? 1 : 2;
|
||||
}
|
||||
|
||||
function f7<T extends boolean>({ prop1: { prop2 } }: { prop1: { prop2: T } }): Ret<T> {
|
||||
return prop2 ? 1 : 2;
|
||||
}
|
||||
|
||||
function f8<T extends boolean>({ prop1 }: T): Ret<T> { // Bad.
|
||||
return prop1 ? 1 : 2;
|
||||
}
|
||||
|
||||
function f9<T extends boolean>(param: { "some prop": T }): Ret<T> {
|
||||
return param["some prop"] ? 1 : 2;
|
||||
}
|
||||
|
||||
// Tests for detection of valid narrowable type parameter references.
|
||||
|
||||
function g1<T extends boolean>(param: T): Ret<T> {
|
||||
return param ? 1 : 2;
|
||||
}
|
||||
|
||||
function g2<T extends boolean>(param: { prop: T }): Ret<T> {
|
||||
return param.prop ? 1 : 2;
|
||||
}
|
||||
|
||||
class Dog {
|
||||
bark(): void {}
|
||||
}
|
||||
|
||||
class Cat {
|
||||
meow(): void {}
|
||||
|
||||
}
|
||||
|
||||
type Type1<T> = { prop: T, prop2: Cat | Dog }
|
||||
|
||||
function g3<T extends boolean>(param: Type1<T>): Ret<T> {
|
||||
return param.prop ? 1 : 2;
|
||||
}
|
||||
|
||||
type TypeUnused<T> = string;
|
||||
|
||||
function g4<T extends boolean>(param: Type1<T>, other: TypeUnused<T>): Ret<T> { // Bad.
|
||||
return param.prop ? 1 : 2;
|
||||
}
|
||||
|
||||
interface Type2<T extends boolean> {
|
||||
prop: T,
|
||||
[s: string]: boolean | undefined,
|
||||
}
|
||||
|
||||
function g5<T extends boolean>(param: Type2<T>): Ret<T> {
|
||||
return param.prop ? 1 : 2;
|
||||
}
|
||||
|
||||
interface Type3<T extends boolean> {
|
||||
prop: T,
|
||||
}
|
||||
|
||||
interface Type3<T extends boolean> {
|
||||
prop2: Cat | Dog,
|
||||
}
|
||||
|
||||
function g6<T extends boolean>(param: Type3<T>): Ret<T> { // Unsupported for now: interface merging.
|
||||
return param.prop ? 1 : 2;
|
||||
}
|
||||
|
||||
type Type4<T, S> = {
|
||||
prop: T,
|
||||
prop2: S[],
|
||||
}
|
||||
|
||||
function g7<T extends boolean, S>(param: Type4<T, S>): Ret<T> {
|
||||
return param.prop ? 1 : 2;
|
||||
}
|
||||
|
||||
function g8<T extends boolean>(param: Type1<T> & { prop2: Cat | Dog }): Ret<T> {
|
||||
return param.prop ? 1 : 2;
|
||||
}
|
||||
|
||||
function g9<T extends boolean>([ prop ]: [T]): Ret<T> { // Unsupported.
|
||||
return prop ? 1 : 2;
|
||||
}
|
||||
|
||||
function g10<T extends boolean>(param: [T]): Ret<T> { // Unsupported.
|
||||
return param[0] ? 1 : 2;
|
||||
}
|
||||
|
||||
function g11<T extends boolean>(param: T[]): Ret<T> { // Bad.
|
||||
return param[0] ? 1 : 2;
|
||||
}
|
||||
|
||||
type Type5<S> = {
|
||||
prop: S,
|
||||
prop2: string[],
|
||||
}
|
||||
|
||||
function g12<T extends boolean>(param: Type5<T>): Ret<T> {
|
||||
return param.prop ? 1 : 2;
|
||||
}
|
||||
|
||||
type Type6<S> = {
|
||||
prop: S,
|
||||
prop2: S[],
|
||||
}
|
||||
|
||||
function g13<T extends boolean>(param: Type6<T>): Ret<T> { // Bad.
|
||||
return param.prop ? 1 : 2;
|
||||
}
|
||||
|
||||
type Type7<T> = {
|
||||
[Key in "prop"]: T
|
||||
}
|
||||
|
||||
function g14<T extends boolean>(param: Type7<T>): Ret<T> { // Unsupported.
|
||||
return param.prop ? 1 : 2;
|
||||
}
|
||||
|
||||
class Class1<T> {
|
||||
prop!: T;
|
||||
}
|
||||
|
||||
function g15<T extends boolean>(param: Class1<T>): Ret<T> { // Unsupported.
|
||||
return param.prop ? 1 : 2;
|
||||
}
|
||||
|
||||
type Type8<T> = {
|
||||
prop: T,
|
||||
}
|
||||
|
||||
type Type9<T> = {
|
||||
prop2: T,
|
||||
}
|
||||
|
||||
function g16<T extends boolean>(param: Type8<Type9<T>["prop2"]>): Ret<T> { // Unsupported.
|
||||
return param.prop ? 1 : 2;
|
||||
}
|
||||
|
||||
// Tests for shadowing and resolving the constructed narrowable reference.
|
||||
|
||||
function h1<T extends boolean>(param: T): Ret<T> {
|
||||
if (param) {
|
||||
const param = false;
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function h2<T extends boolean>({ prop }: { prop: T}): Ret<T> {
|
||||
if (prop) {
|
||||
const prop = false;
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function h3<T extends boolean>(param: { prop: T}): Ret<T> {
|
||||
if (param.prop) {
|
||||
const param = { prop: false };
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function h4<T extends boolean>(param: { "some prop": T }): Ret<T> {
|
||||
if (param["some prop"]) {
|
||||
const param = { "some prop": false };
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function h5<T extends boolean>(param: T): Ret<T> {
|
||||
{
|
||||
const param = true;
|
||||
if (param) {
|
||||
return 1; // Bad.
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user