mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-10 18:04:18 -05:00
Improve logic that chooses co- vs. contra-variant inferences (#52123)
This commit is contained in:
@@ -24504,11 +24504,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (signature) {
|
||||
const inferredCovariantType = inference.candidates ? getCovariantInference(inference, signature) : undefined;
|
||||
if (inference.contraCandidates) {
|
||||
// If we have both co- and contra-variant inferences, we prefer the contra-variant inference
|
||||
// unless the co-variant inference is a subtype of some contra-variant inference and not 'never'.
|
||||
inferredType = inferredCovariantType && !(inferredCovariantType.flags & TypeFlags.Never) &&
|
||||
some(inference.contraCandidates, t => isTypeSubtypeOf(inferredCovariantType, t)) ?
|
||||
inferredCovariantType : getContravariantInference(inference);
|
||||
// If we have both co- and contra-variant inferences, we use the co-variant inference if it is not 'never',
|
||||
// it is a subtype of some contra-variant inference, and no other type parameter is constrained to this type
|
||||
// parameter and has inferences that would conflict. Otherwise, we use the contra-variant inference.
|
||||
const useCovariantType = inferredCovariantType && !(inferredCovariantType.flags & TypeFlags.Never) &&
|
||||
some(inference.contraCandidates, t => isTypeSubtypeOf(inferredCovariantType, t)) &&
|
||||
every(context.inferences, other => other === inference ||
|
||||
getConstraintOfTypeParameter(other.typeParameter) !== inference.typeParameter ||
|
||||
every(other.candidates, t => isTypeSubtypeOf(t, inferredCovariantType)));
|
||||
inferredType = useCovariantType ? inferredCovariantType : getContravariantInference(inference);
|
||||
}
|
||||
else if (inferredCovariantType) {
|
||||
inferredType = inferredCovariantType;
|
||||
|
||||
140
tests/baselines/reference/coAndContraVariantInferences2.js
Normal file
140
tests/baselines/reference/coAndContraVariantInferences2.js
Normal file
@@ -0,0 +1,140 @@
|
||||
//// [coAndContraVariantInferences2.ts]
|
||||
interface A { a: string }
|
||||
interface B extends A { b: string }
|
||||
interface C extends A { c: string }
|
||||
|
||||
declare function cast<T, U extends T>(x: T, test: (x: T) => x is U): U;
|
||||
|
||||
declare function isC(x: A): x is C;
|
||||
|
||||
function f1(a: A, b: B) {
|
||||
const x1 = cast(a, isC); // cast<A, C>
|
||||
const x2 = cast(b, isC); // cast<A, C>
|
||||
}
|
||||
|
||||
declare function useA(a: A): void;
|
||||
|
||||
declare function consume<T, U extends T>(t: T, u: U, f: (x: T) => void): void;
|
||||
|
||||
function f2(b: B, c: C) {
|
||||
consume(b, c, useA); // consume<A, C>
|
||||
consume(c, b, useA); // consume<A, B>
|
||||
consume(b, b, useA); // consume<B, B>
|
||||
consume(c, c, useA); // consume<C, C>
|
||||
}
|
||||
|
||||
// Repro from #52111
|
||||
|
||||
enum SyntaxKind {
|
||||
Block,
|
||||
Identifier,
|
||||
CaseClause,
|
||||
FunctionExpression,
|
||||
FunctionDeclaration,
|
||||
}
|
||||
|
||||
interface Node { kind: SyntaxKind; }
|
||||
interface Expression extends Node { _expressionBrand: any; }
|
||||
interface Declaration extends Node { _declarationBrand: any; }
|
||||
interface Block extends Node { kind: SyntaxKind.Block; }
|
||||
interface Identifier extends Expression, Declaration { kind: SyntaxKind.Identifier; }
|
||||
interface CaseClause extends Node { kind: SyntaxKind.CaseClause; }
|
||||
interface FunctionDeclaration extends Declaration { kind: SyntaxKind.FunctionDeclaration; }
|
||||
|
||||
type HasLocals = Block | FunctionDeclaration;
|
||||
declare function canHaveLocals(node: Node): node is HasLocals;
|
||||
|
||||
declare function assertNode<T extends Node, U extends T>(node: T | undefined, test: (node: T) => node is U): asserts node is U;
|
||||
declare function assertNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined): void;
|
||||
|
||||
function foo(node: FunctionDeclaration | CaseClause) {
|
||||
assertNode(node, canHaveLocals); // assertNode<Node, HasLocals>
|
||||
node; // FunctionDeclaration
|
||||
}
|
||||
|
||||
declare function isExpression(node: Node): node is Expression;
|
||||
|
||||
declare function tryCast<TOut extends TIn, TIn = any>(value: TIn | undefined, test: (value: TIn) => value is TOut): TOut;
|
||||
|
||||
function bar(node: Identifier | FunctionDeclaration) {
|
||||
const a = tryCast(node, isExpression); // tryCast<Expression, Node>
|
||||
}
|
||||
|
||||
// Repro from #49924
|
||||
|
||||
const enum SyntaxKind1 {
|
||||
ClassExpression,
|
||||
ClassStatement,
|
||||
}
|
||||
|
||||
interface Node1 {
|
||||
kind: SyntaxKind1;
|
||||
}
|
||||
|
||||
interface Statement1 extends Node1 {
|
||||
_statementBrand: any;
|
||||
}
|
||||
|
||||
interface ClassExpression1 extends Node1 {
|
||||
kind: SyntaxKind1.ClassExpression;
|
||||
}
|
||||
|
||||
interface ClassStatement1 extends Statement1 {
|
||||
kind: SyntaxKind1.ClassStatement;
|
||||
}
|
||||
|
||||
type ClassLike1 = ClassExpression1 | ClassStatement1;
|
||||
|
||||
declare function isClassLike(node: Node1): node is ClassLike1;
|
||||
|
||||
declare const statement: Statement1 | undefined;
|
||||
|
||||
const maybeClassStatement = tryCast(statement, isClassLike); // ClassLike1
|
||||
|
||||
// Repro from #49924
|
||||
|
||||
interface TypeNode extends Node {
|
||||
typeInfo: string;
|
||||
}
|
||||
|
||||
interface NodeArray<T extends Node> extends Array<T> {
|
||||
someProp: string;
|
||||
}
|
||||
|
||||
declare function isNodeArray<T extends Node>(array: readonly T[]): array is NodeArray<T>;
|
||||
|
||||
declare const types: readonly TypeNode[];
|
||||
|
||||
const x = tryCast(types, isNodeArray); // NodeAray<TypeNode>
|
||||
|
||||
|
||||
//// [coAndContraVariantInferences2.js]
|
||||
"use strict";
|
||||
function f1(a, b) {
|
||||
var x1 = cast(a, isC); // cast<A, C>
|
||||
var x2 = cast(b, isC); // cast<A, C>
|
||||
}
|
||||
function f2(b, c) {
|
||||
consume(b, c, useA); // consume<A, C>
|
||||
consume(c, b, useA); // consume<A, B>
|
||||
consume(b, b, useA); // consume<B, B>
|
||||
consume(c, c, useA); // consume<C, C>
|
||||
}
|
||||
// Repro from #52111
|
||||
var SyntaxKind;
|
||||
(function (SyntaxKind) {
|
||||
SyntaxKind[SyntaxKind["Block"] = 0] = "Block";
|
||||
SyntaxKind[SyntaxKind["Identifier"] = 1] = "Identifier";
|
||||
SyntaxKind[SyntaxKind["CaseClause"] = 2] = "CaseClause";
|
||||
SyntaxKind[SyntaxKind["FunctionExpression"] = 3] = "FunctionExpression";
|
||||
SyntaxKind[SyntaxKind["FunctionDeclaration"] = 4] = "FunctionDeclaration";
|
||||
})(SyntaxKind || (SyntaxKind = {}));
|
||||
function foo(node) {
|
||||
assertNode(node, canHaveLocals); // assertNode<Node, HasLocals>
|
||||
node; // FunctionDeclaration
|
||||
}
|
||||
function bar(node) {
|
||||
var a = tryCast(node, isExpression); // tryCast<Expression, Node>
|
||||
}
|
||||
var maybeClassStatement = tryCast(statement, isClassLike); // ClassLike1
|
||||
var x = tryCast(types, isNodeArray); // NodeAray<TypeNode>
|
||||
367
tests/baselines/reference/coAndContraVariantInferences2.symbols
Normal file
367
tests/baselines/reference/coAndContraVariantInferences2.symbols
Normal file
@@ -0,0 +1,367 @@
|
||||
=== tests/cases/compiler/coAndContraVariantInferences2.ts ===
|
||||
interface A { a: string }
|
||||
>A : Symbol(A, Decl(coAndContraVariantInferences2.ts, 0, 0))
|
||||
>a : Symbol(A.a, Decl(coAndContraVariantInferences2.ts, 0, 13))
|
||||
|
||||
interface B extends A { b: string }
|
||||
>B : Symbol(B, Decl(coAndContraVariantInferences2.ts, 0, 25))
|
||||
>A : Symbol(A, Decl(coAndContraVariantInferences2.ts, 0, 0))
|
||||
>b : Symbol(B.b, Decl(coAndContraVariantInferences2.ts, 1, 23))
|
||||
|
||||
interface C extends A { c: string }
|
||||
>C : Symbol(C, Decl(coAndContraVariantInferences2.ts, 1, 35))
|
||||
>A : Symbol(A, Decl(coAndContraVariantInferences2.ts, 0, 0))
|
||||
>c : Symbol(C.c, Decl(coAndContraVariantInferences2.ts, 2, 23))
|
||||
|
||||
declare function cast<T, U extends T>(x: T, test: (x: T) => x is U): U;
|
||||
>cast : Symbol(cast, Decl(coAndContraVariantInferences2.ts, 2, 35))
|
||||
>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 4, 22))
|
||||
>U : Symbol(U, Decl(coAndContraVariantInferences2.ts, 4, 24))
|
||||
>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 4, 22))
|
||||
>x : Symbol(x, Decl(coAndContraVariantInferences2.ts, 4, 38))
|
||||
>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 4, 22))
|
||||
>test : Symbol(test, Decl(coAndContraVariantInferences2.ts, 4, 43))
|
||||
>x : Symbol(x, Decl(coAndContraVariantInferences2.ts, 4, 51))
|
||||
>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 4, 22))
|
||||
>x : Symbol(x, Decl(coAndContraVariantInferences2.ts, 4, 51))
|
||||
>U : Symbol(U, Decl(coAndContraVariantInferences2.ts, 4, 24))
|
||||
>U : Symbol(U, Decl(coAndContraVariantInferences2.ts, 4, 24))
|
||||
|
||||
declare function isC(x: A): x is C;
|
||||
>isC : Symbol(isC, Decl(coAndContraVariantInferences2.ts, 4, 71))
|
||||
>x : Symbol(x, Decl(coAndContraVariantInferences2.ts, 6, 21))
|
||||
>A : Symbol(A, Decl(coAndContraVariantInferences2.ts, 0, 0))
|
||||
>x : Symbol(x, Decl(coAndContraVariantInferences2.ts, 6, 21))
|
||||
>C : Symbol(C, Decl(coAndContraVariantInferences2.ts, 1, 35))
|
||||
|
||||
function f1(a: A, b: B) {
|
||||
>f1 : Symbol(f1, Decl(coAndContraVariantInferences2.ts, 6, 35))
|
||||
>a : Symbol(a, Decl(coAndContraVariantInferences2.ts, 8, 12))
|
||||
>A : Symbol(A, Decl(coAndContraVariantInferences2.ts, 0, 0))
|
||||
>b : Symbol(b, Decl(coAndContraVariantInferences2.ts, 8, 17))
|
||||
>B : Symbol(B, Decl(coAndContraVariantInferences2.ts, 0, 25))
|
||||
|
||||
const x1 = cast(a, isC); // cast<A, C>
|
||||
>x1 : Symbol(x1, Decl(coAndContraVariantInferences2.ts, 9, 9))
|
||||
>cast : Symbol(cast, Decl(coAndContraVariantInferences2.ts, 2, 35))
|
||||
>a : Symbol(a, Decl(coAndContraVariantInferences2.ts, 8, 12))
|
||||
>isC : Symbol(isC, Decl(coAndContraVariantInferences2.ts, 4, 71))
|
||||
|
||||
const x2 = cast(b, isC); // cast<A, C>
|
||||
>x2 : Symbol(x2, Decl(coAndContraVariantInferences2.ts, 10, 9))
|
||||
>cast : Symbol(cast, Decl(coAndContraVariantInferences2.ts, 2, 35))
|
||||
>b : Symbol(b, Decl(coAndContraVariantInferences2.ts, 8, 17))
|
||||
>isC : Symbol(isC, Decl(coAndContraVariantInferences2.ts, 4, 71))
|
||||
}
|
||||
|
||||
declare function useA(a: A): void;
|
||||
>useA : Symbol(useA, Decl(coAndContraVariantInferences2.ts, 11, 1))
|
||||
>a : Symbol(a, Decl(coAndContraVariantInferences2.ts, 13, 22))
|
||||
>A : Symbol(A, Decl(coAndContraVariantInferences2.ts, 0, 0))
|
||||
|
||||
declare function consume<T, U extends T>(t: T, u: U, f: (x: T) => void): void;
|
||||
>consume : Symbol(consume, Decl(coAndContraVariantInferences2.ts, 13, 34))
|
||||
>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 15, 25))
|
||||
>U : Symbol(U, Decl(coAndContraVariantInferences2.ts, 15, 27))
|
||||
>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 15, 25))
|
||||
>t : Symbol(t, Decl(coAndContraVariantInferences2.ts, 15, 41))
|
||||
>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 15, 25))
|
||||
>u : Symbol(u, Decl(coAndContraVariantInferences2.ts, 15, 46))
|
||||
>U : Symbol(U, Decl(coAndContraVariantInferences2.ts, 15, 27))
|
||||
>f : Symbol(f, Decl(coAndContraVariantInferences2.ts, 15, 52))
|
||||
>x : Symbol(x, Decl(coAndContraVariantInferences2.ts, 15, 57))
|
||||
>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 15, 25))
|
||||
|
||||
function f2(b: B, c: C) {
|
||||
>f2 : Symbol(f2, Decl(coAndContraVariantInferences2.ts, 15, 78))
|
||||
>b : Symbol(b, Decl(coAndContraVariantInferences2.ts, 17, 12))
|
||||
>B : Symbol(B, Decl(coAndContraVariantInferences2.ts, 0, 25))
|
||||
>c : Symbol(c, Decl(coAndContraVariantInferences2.ts, 17, 17))
|
||||
>C : Symbol(C, Decl(coAndContraVariantInferences2.ts, 1, 35))
|
||||
|
||||
consume(b, c, useA); // consume<A, C>
|
||||
>consume : Symbol(consume, Decl(coAndContraVariantInferences2.ts, 13, 34))
|
||||
>b : Symbol(b, Decl(coAndContraVariantInferences2.ts, 17, 12))
|
||||
>c : Symbol(c, Decl(coAndContraVariantInferences2.ts, 17, 17))
|
||||
>useA : Symbol(useA, Decl(coAndContraVariantInferences2.ts, 11, 1))
|
||||
|
||||
consume(c, b, useA); // consume<A, B>
|
||||
>consume : Symbol(consume, Decl(coAndContraVariantInferences2.ts, 13, 34))
|
||||
>c : Symbol(c, Decl(coAndContraVariantInferences2.ts, 17, 17))
|
||||
>b : Symbol(b, Decl(coAndContraVariantInferences2.ts, 17, 12))
|
||||
>useA : Symbol(useA, Decl(coAndContraVariantInferences2.ts, 11, 1))
|
||||
|
||||
consume(b, b, useA); // consume<B, B>
|
||||
>consume : Symbol(consume, Decl(coAndContraVariantInferences2.ts, 13, 34))
|
||||
>b : Symbol(b, Decl(coAndContraVariantInferences2.ts, 17, 12))
|
||||
>b : Symbol(b, Decl(coAndContraVariantInferences2.ts, 17, 12))
|
||||
>useA : Symbol(useA, Decl(coAndContraVariantInferences2.ts, 11, 1))
|
||||
|
||||
consume(c, c, useA); // consume<C, C>
|
||||
>consume : Symbol(consume, Decl(coAndContraVariantInferences2.ts, 13, 34))
|
||||
>c : Symbol(c, Decl(coAndContraVariantInferences2.ts, 17, 17))
|
||||
>c : Symbol(c, Decl(coAndContraVariantInferences2.ts, 17, 17))
|
||||
>useA : Symbol(useA, Decl(coAndContraVariantInferences2.ts, 11, 1))
|
||||
}
|
||||
|
||||
// Repro from #52111
|
||||
|
||||
enum SyntaxKind {
|
||||
>SyntaxKind : Symbol(SyntaxKind, Decl(coAndContraVariantInferences2.ts, 22, 1))
|
||||
|
||||
Block,
|
||||
>Block : Symbol(SyntaxKind.Block, Decl(coAndContraVariantInferences2.ts, 26, 17))
|
||||
|
||||
Identifier,
|
||||
>Identifier : Symbol(SyntaxKind.Identifier, Decl(coAndContraVariantInferences2.ts, 27, 10))
|
||||
|
||||
CaseClause,
|
||||
>CaseClause : Symbol(SyntaxKind.CaseClause, Decl(coAndContraVariantInferences2.ts, 28, 15))
|
||||
|
||||
FunctionExpression,
|
||||
>FunctionExpression : Symbol(SyntaxKind.FunctionExpression, Decl(coAndContraVariantInferences2.ts, 29, 15))
|
||||
|
||||
FunctionDeclaration,
|
||||
>FunctionDeclaration : Symbol(SyntaxKind.FunctionDeclaration, Decl(coAndContraVariantInferences2.ts, 30, 23))
|
||||
}
|
||||
|
||||
interface Node { kind: SyntaxKind; }
|
||||
>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1))
|
||||
>kind : Symbol(Node.kind, Decl(coAndContraVariantInferences2.ts, 34, 16))
|
||||
>SyntaxKind : Symbol(SyntaxKind, Decl(coAndContraVariantInferences2.ts, 22, 1))
|
||||
|
||||
interface Expression extends Node { _expressionBrand: any; }
|
||||
>Expression : Symbol(Expression, Decl(coAndContraVariantInferences2.ts, 34, 36))
|
||||
>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1))
|
||||
>_expressionBrand : Symbol(Expression._expressionBrand, Decl(coAndContraVariantInferences2.ts, 35, 35))
|
||||
|
||||
interface Declaration extends Node { _declarationBrand: any; }
|
||||
>Declaration : Symbol(Declaration, Decl(coAndContraVariantInferences2.ts, 35, 60))
|
||||
>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1))
|
||||
>_declarationBrand : Symbol(Declaration._declarationBrand, Decl(coAndContraVariantInferences2.ts, 36, 36))
|
||||
|
||||
interface Block extends Node { kind: SyntaxKind.Block; }
|
||||
>Block : Symbol(Block, Decl(coAndContraVariantInferences2.ts, 36, 62))
|
||||
>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1))
|
||||
>kind : Symbol(Block.kind, Decl(coAndContraVariantInferences2.ts, 37, 30))
|
||||
>SyntaxKind : Symbol(SyntaxKind, Decl(coAndContraVariantInferences2.ts, 22, 1))
|
||||
>Block : Symbol(SyntaxKind.Block, Decl(coAndContraVariantInferences2.ts, 26, 17))
|
||||
|
||||
interface Identifier extends Expression, Declaration { kind: SyntaxKind.Identifier; }
|
||||
>Identifier : Symbol(Identifier, Decl(coAndContraVariantInferences2.ts, 37, 56))
|
||||
>Expression : Symbol(Expression, Decl(coAndContraVariantInferences2.ts, 34, 36))
|
||||
>Declaration : Symbol(Declaration, Decl(coAndContraVariantInferences2.ts, 35, 60))
|
||||
>kind : Symbol(Identifier.kind, Decl(coAndContraVariantInferences2.ts, 38, 54))
|
||||
>SyntaxKind : Symbol(SyntaxKind, Decl(coAndContraVariantInferences2.ts, 22, 1))
|
||||
>Identifier : Symbol(SyntaxKind.Identifier, Decl(coAndContraVariantInferences2.ts, 27, 10))
|
||||
|
||||
interface CaseClause extends Node { kind: SyntaxKind.CaseClause; }
|
||||
>CaseClause : Symbol(CaseClause, Decl(coAndContraVariantInferences2.ts, 38, 85))
|
||||
>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1))
|
||||
>kind : Symbol(CaseClause.kind, Decl(coAndContraVariantInferences2.ts, 39, 35))
|
||||
>SyntaxKind : Symbol(SyntaxKind, Decl(coAndContraVariantInferences2.ts, 22, 1))
|
||||
>CaseClause : Symbol(SyntaxKind.CaseClause, Decl(coAndContraVariantInferences2.ts, 28, 15))
|
||||
|
||||
interface FunctionDeclaration extends Declaration { kind: SyntaxKind.FunctionDeclaration; }
|
||||
>FunctionDeclaration : Symbol(FunctionDeclaration, Decl(coAndContraVariantInferences2.ts, 39, 66))
|
||||
>Declaration : Symbol(Declaration, Decl(coAndContraVariantInferences2.ts, 35, 60))
|
||||
>kind : Symbol(FunctionDeclaration.kind, Decl(coAndContraVariantInferences2.ts, 40, 51))
|
||||
>SyntaxKind : Symbol(SyntaxKind, Decl(coAndContraVariantInferences2.ts, 22, 1))
|
||||
>FunctionDeclaration : Symbol(SyntaxKind.FunctionDeclaration, Decl(coAndContraVariantInferences2.ts, 30, 23))
|
||||
|
||||
type HasLocals = Block | FunctionDeclaration;
|
||||
>HasLocals : Symbol(HasLocals, Decl(coAndContraVariantInferences2.ts, 40, 91))
|
||||
>Block : Symbol(Block, Decl(coAndContraVariantInferences2.ts, 36, 62))
|
||||
>FunctionDeclaration : Symbol(FunctionDeclaration, Decl(coAndContraVariantInferences2.ts, 39, 66))
|
||||
|
||||
declare function canHaveLocals(node: Node): node is HasLocals;
|
||||
>canHaveLocals : Symbol(canHaveLocals, Decl(coAndContraVariantInferences2.ts, 42, 45))
|
||||
>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 43, 31))
|
||||
>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1))
|
||||
>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 43, 31))
|
||||
>HasLocals : Symbol(HasLocals, Decl(coAndContraVariantInferences2.ts, 40, 91))
|
||||
|
||||
declare function assertNode<T extends Node, U extends T>(node: T | undefined, test: (node: T) => node is U): asserts node is U;
|
||||
>assertNode : Symbol(assertNode, Decl(coAndContraVariantInferences2.ts, 43, 62), Decl(coAndContraVariantInferences2.ts, 45, 127))
|
||||
>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 45, 28))
|
||||
>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1))
|
||||
>U : Symbol(U, Decl(coAndContraVariantInferences2.ts, 45, 43))
|
||||
>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 45, 28))
|
||||
>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 45, 57))
|
||||
>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 45, 28))
|
||||
>test : Symbol(test, Decl(coAndContraVariantInferences2.ts, 45, 77))
|
||||
>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 45, 85))
|
||||
>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 45, 28))
|
||||
>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 45, 85))
|
||||
>U : Symbol(U, Decl(coAndContraVariantInferences2.ts, 45, 43))
|
||||
>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 45, 57))
|
||||
>U : Symbol(U, Decl(coAndContraVariantInferences2.ts, 45, 43))
|
||||
|
||||
declare function assertNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined): void;
|
||||
>assertNode : Symbol(assertNode, Decl(coAndContraVariantInferences2.ts, 43, 62), Decl(coAndContraVariantInferences2.ts, 45, 127))
|
||||
>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 46, 28))
|
||||
>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1))
|
||||
>test : Symbol(test, Decl(coAndContraVariantInferences2.ts, 46, 51))
|
||||
>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 46, 60))
|
||||
>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1))
|
||||
|
||||
function foo(node: FunctionDeclaration | CaseClause) {
|
||||
>foo : Symbol(foo, Decl(coAndContraVariantInferences2.ts, 46, 103))
|
||||
>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 48, 13))
|
||||
>FunctionDeclaration : Symbol(FunctionDeclaration, Decl(coAndContraVariantInferences2.ts, 39, 66))
|
||||
>CaseClause : Symbol(CaseClause, Decl(coAndContraVariantInferences2.ts, 38, 85))
|
||||
|
||||
assertNode(node, canHaveLocals); // assertNode<Node, HasLocals>
|
||||
>assertNode : Symbol(assertNode, Decl(coAndContraVariantInferences2.ts, 43, 62), Decl(coAndContraVariantInferences2.ts, 45, 127))
|
||||
>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 48, 13))
|
||||
>canHaveLocals : Symbol(canHaveLocals, Decl(coAndContraVariantInferences2.ts, 42, 45))
|
||||
|
||||
node; // FunctionDeclaration
|
||||
>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 48, 13))
|
||||
}
|
||||
|
||||
declare function isExpression(node: Node): node is Expression;
|
||||
>isExpression : Symbol(isExpression, Decl(coAndContraVariantInferences2.ts, 51, 1))
|
||||
>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 53, 30))
|
||||
>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1))
|
||||
>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 53, 30))
|
||||
>Expression : Symbol(Expression, Decl(coAndContraVariantInferences2.ts, 34, 36))
|
||||
|
||||
declare function tryCast<TOut extends TIn, TIn = any>(value: TIn | undefined, test: (value: TIn) => value is TOut): TOut;
|
||||
>tryCast : Symbol(tryCast, Decl(coAndContraVariantInferences2.ts, 53, 62))
|
||||
>TOut : Symbol(TOut, Decl(coAndContraVariantInferences2.ts, 55, 25))
|
||||
>TIn : Symbol(TIn, Decl(coAndContraVariantInferences2.ts, 55, 42))
|
||||
>TIn : Symbol(TIn, Decl(coAndContraVariantInferences2.ts, 55, 42))
|
||||
>value : Symbol(value, Decl(coAndContraVariantInferences2.ts, 55, 54))
|
||||
>TIn : Symbol(TIn, Decl(coAndContraVariantInferences2.ts, 55, 42))
|
||||
>test : Symbol(test, Decl(coAndContraVariantInferences2.ts, 55, 77))
|
||||
>value : Symbol(value, Decl(coAndContraVariantInferences2.ts, 55, 85))
|
||||
>TIn : Symbol(TIn, Decl(coAndContraVariantInferences2.ts, 55, 42))
|
||||
>value : Symbol(value, Decl(coAndContraVariantInferences2.ts, 55, 85))
|
||||
>TOut : Symbol(TOut, Decl(coAndContraVariantInferences2.ts, 55, 25))
|
||||
>TOut : Symbol(TOut, Decl(coAndContraVariantInferences2.ts, 55, 25))
|
||||
|
||||
function bar(node: Identifier | FunctionDeclaration) {
|
||||
>bar : Symbol(bar, Decl(coAndContraVariantInferences2.ts, 55, 121))
|
||||
>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 57, 13))
|
||||
>Identifier : Symbol(Identifier, Decl(coAndContraVariantInferences2.ts, 37, 56))
|
||||
>FunctionDeclaration : Symbol(FunctionDeclaration, Decl(coAndContraVariantInferences2.ts, 39, 66))
|
||||
|
||||
const a = tryCast(node, isExpression); // tryCast<Expression, Node>
|
||||
>a : Symbol(a, Decl(coAndContraVariantInferences2.ts, 58, 9))
|
||||
>tryCast : Symbol(tryCast, Decl(coAndContraVariantInferences2.ts, 53, 62))
|
||||
>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 57, 13))
|
||||
>isExpression : Symbol(isExpression, Decl(coAndContraVariantInferences2.ts, 51, 1))
|
||||
}
|
||||
|
||||
// Repro from #49924
|
||||
|
||||
const enum SyntaxKind1 {
|
||||
>SyntaxKind1 : Symbol(SyntaxKind1, Decl(coAndContraVariantInferences2.ts, 59, 1))
|
||||
|
||||
ClassExpression,
|
||||
>ClassExpression : Symbol(SyntaxKind1.ClassExpression, Decl(coAndContraVariantInferences2.ts, 63, 24))
|
||||
|
||||
ClassStatement,
|
||||
>ClassStatement : Symbol(SyntaxKind1.ClassStatement, Decl(coAndContraVariantInferences2.ts, 64, 20))
|
||||
}
|
||||
|
||||
interface Node1 {
|
||||
>Node1 : Symbol(Node1, Decl(coAndContraVariantInferences2.ts, 66, 1))
|
||||
|
||||
kind: SyntaxKind1;
|
||||
>kind : Symbol(Node1.kind, Decl(coAndContraVariantInferences2.ts, 68, 17))
|
||||
>SyntaxKind1 : Symbol(SyntaxKind1, Decl(coAndContraVariantInferences2.ts, 59, 1))
|
||||
}
|
||||
|
||||
interface Statement1 extends Node1 {
|
||||
>Statement1 : Symbol(Statement1, Decl(coAndContraVariantInferences2.ts, 70, 1))
|
||||
>Node1 : Symbol(Node1, Decl(coAndContraVariantInferences2.ts, 66, 1))
|
||||
|
||||
_statementBrand: any;
|
||||
>_statementBrand : Symbol(Statement1._statementBrand, Decl(coAndContraVariantInferences2.ts, 72, 36))
|
||||
}
|
||||
|
||||
interface ClassExpression1 extends Node1 {
|
||||
>ClassExpression1 : Symbol(ClassExpression1, Decl(coAndContraVariantInferences2.ts, 74, 1))
|
||||
>Node1 : Symbol(Node1, Decl(coAndContraVariantInferences2.ts, 66, 1))
|
||||
|
||||
kind: SyntaxKind1.ClassExpression;
|
||||
>kind : Symbol(ClassExpression1.kind, Decl(coAndContraVariantInferences2.ts, 76, 42))
|
||||
>SyntaxKind1 : Symbol(SyntaxKind1, Decl(coAndContraVariantInferences2.ts, 59, 1))
|
||||
>ClassExpression : Symbol(SyntaxKind1.ClassExpression, Decl(coAndContraVariantInferences2.ts, 63, 24))
|
||||
}
|
||||
|
||||
interface ClassStatement1 extends Statement1 {
|
||||
>ClassStatement1 : Symbol(ClassStatement1, Decl(coAndContraVariantInferences2.ts, 78, 1))
|
||||
>Statement1 : Symbol(Statement1, Decl(coAndContraVariantInferences2.ts, 70, 1))
|
||||
|
||||
kind: SyntaxKind1.ClassStatement;
|
||||
>kind : Symbol(ClassStatement1.kind, Decl(coAndContraVariantInferences2.ts, 80, 46))
|
||||
>SyntaxKind1 : Symbol(SyntaxKind1, Decl(coAndContraVariantInferences2.ts, 59, 1))
|
||||
>ClassStatement : Symbol(SyntaxKind1.ClassStatement, Decl(coAndContraVariantInferences2.ts, 64, 20))
|
||||
}
|
||||
|
||||
type ClassLike1 = ClassExpression1 | ClassStatement1;
|
||||
>ClassLike1 : Symbol(ClassLike1, Decl(coAndContraVariantInferences2.ts, 82, 1))
|
||||
>ClassExpression1 : Symbol(ClassExpression1, Decl(coAndContraVariantInferences2.ts, 74, 1))
|
||||
>ClassStatement1 : Symbol(ClassStatement1, Decl(coAndContraVariantInferences2.ts, 78, 1))
|
||||
|
||||
declare function isClassLike(node: Node1): node is ClassLike1;
|
||||
>isClassLike : Symbol(isClassLike, Decl(coAndContraVariantInferences2.ts, 84, 53))
|
||||
>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 86, 29))
|
||||
>Node1 : Symbol(Node1, Decl(coAndContraVariantInferences2.ts, 66, 1))
|
||||
>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 86, 29))
|
||||
>ClassLike1 : Symbol(ClassLike1, Decl(coAndContraVariantInferences2.ts, 82, 1))
|
||||
|
||||
declare const statement: Statement1 | undefined;
|
||||
>statement : Symbol(statement, Decl(coAndContraVariantInferences2.ts, 88, 13))
|
||||
>Statement1 : Symbol(Statement1, Decl(coAndContraVariantInferences2.ts, 70, 1))
|
||||
|
||||
const maybeClassStatement = tryCast(statement, isClassLike); // ClassLike1
|
||||
>maybeClassStatement : Symbol(maybeClassStatement, Decl(coAndContraVariantInferences2.ts, 90, 5))
|
||||
>tryCast : Symbol(tryCast, Decl(coAndContraVariantInferences2.ts, 53, 62))
|
||||
>statement : Symbol(statement, Decl(coAndContraVariantInferences2.ts, 88, 13))
|
||||
>isClassLike : Symbol(isClassLike, Decl(coAndContraVariantInferences2.ts, 84, 53))
|
||||
|
||||
// Repro from #49924
|
||||
|
||||
interface TypeNode extends Node {
|
||||
>TypeNode : Symbol(TypeNode, Decl(coAndContraVariantInferences2.ts, 90, 60))
|
||||
>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1))
|
||||
|
||||
typeInfo: string;
|
||||
>typeInfo : Symbol(TypeNode.typeInfo, Decl(coAndContraVariantInferences2.ts, 94, 33))
|
||||
}
|
||||
|
||||
interface NodeArray<T extends Node> extends Array<T> {
|
||||
>NodeArray : Symbol(NodeArray, Decl(coAndContraVariantInferences2.ts, 96, 1))
|
||||
>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 98, 20))
|
||||
>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1))
|
||||
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 98, 20))
|
||||
|
||||
someProp: string;
|
||||
>someProp : Symbol(NodeArray.someProp, Decl(coAndContraVariantInferences2.ts, 98, 54))
|
||||
}
|
||||
|
||||
declare function isNodeArray<T extends Node>(array: readonly T[]): array is NodeArray<T>;
|
||||
>isNodeArray : Symbol(isNodeArray, Decl(coAndContraVariantInferences2.ts, 100, 1))
|
||||
>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 102, 29))
|
||||
>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1))
|
||||
>array : Symbol(array, Decl(coAndContraVariantInferences2.ts, 102, 45))
|
||||
>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 102, 29))
|
||||
>array : Symbol(array, Decl(coAndContraVariantInferences2.ts, 102, 45))
|
||||
>NodeArray : Symbol(NodeArray, Decl(coAndContraVariantInferences2.ts, 96, 1))
|
||||
>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 102, 29))
|
||||
|
||||
declare const types: readonly TypeNode[];
|
||||
>types : Symbol(types, Decl(coAndContraVariantInferences2.ts, 104, 13))
|
||||
>TypeNode : Symbol(TypeNode, Decl(coAndContraVariantInferences2.ts, 90, 60))
|
||||
|
||||
const x = tryCast(types, isNodeArray); // NodeAray<TypeNode>
|
||||
>x : Symbol(x, Decl(coAndContraVariantInferences2.ts, 106, 5))
|
||||
>tryCast : Symbol(tryCast, Decl(coAndContraVariantInferences2.ts, 53, 62))
|
||||
>types : Symbol(types, Decl(coAndContraVariantInferences2.ts, 104, 13))
|
||||
>isNodeArray : Symbol(isNodeArray, Decl(coAndContraVariantInferences2.ts, 100, 1))
|
||||
|
||||
263
tests/baselines/reference/coAndContraVariantInferences2.types
Normal file
263
tests/baselines/reference/coAndContraVariantInferences2.types
Normal file
@@ -0,0 +1,263 @@
|
||||
=== tests/cases/compiler/coAndContraVariantInferences2.ts ===
|
||||
interface A { a: string }
|
||||
>a : string
|
||||
|
||||
interface B extends A { b: string }
|
||||
>b : string
|
||||
|
||||
interface C extends A { c: string }
|
||||
>c : string
|
||||
|
||||
declare function cast<T, U extends T>(x: T, test: (x: T) => x is U): U;
|
||||
>cast : <T, U extends T>(x: T, test: (x: T) => x is U) => U
|
||||
>x : T
|
||||
>test : (x: T) => x is U
|
||||
>x : T
|
||||
|
||||
declare function isC(x: A): x is C;
|
||||
>isC : (x: A) => x is C
|
||||
>x : A
|
||||
|
||||
function f1(a: A, b: B) {
|
||||
>f1 : (a: A, b: B) => void
|
||||
>a : A
|
||||
>b : B
|
||||
|
||||
const x1 = cast(a, isC); // cast<A, C>
|
||||
>x1 : C
|
||||
>cast(a, isC) : C
|
||||
>cast : <T, U extends T>(x: T, test: (x: T) => x is U) => U
|
||||
>a : A
|
||||
>isC : (x: A) => x is C
|
||||
|
||||
const x2 = cast(b, isC); // cast<A, C>
|
||||
>x2 : C
|
||||
>cast(b, isC) : C
|
||||
>cast : <T, U extends T>(x: T, test: (x: T) => x is U) => U
|
||||
>b : B
|
||||
>isC : (x: A) => x is C
|
||||
}
|
||||
|
||||
declare function useA(a: A): void;
|
||||
>useA : (a: A) => void
|
||||
>a : A
|
||||
|
||||
declare function consume<T, U extends T>(t: T, u: U, f: (x: T) => void): void;
|
||||
>consume : <T, U extends T>(t: T, u: U, f: (x: T) => void) => void
|
||||
>t : T
|
||||
>u : U
|
||||
>f : (x: T) => void
|
||||
>x : T
|
||||
|
||||
function f2(b: B, c: C) {
|
||||
>f2 : (b: B, c: C) => void
|
||||
>b : B
|
||||
>c : C
|
||||
|
||||
consume(b, c, useA); // consume<A, C>
|
||||
>consume(b, c, useA) : void
|
||||
>consume : <T, U extends T>(t: T, u: U, f: (x: T) => void) => void
|
||||
>b : B
|
||||
>c : C
|
||||
>useA : (a: A) => void
|
||||
|
||||
consume(c, b, useA); // consume<A, B>
|
||||
>consume(c, b, useA) : void
|
||||
>consume : <T, U extends T>(t: T, u: U, f: (x: T) => void) => void
|
||||
>c : C
|
||||
>b : B
|
||||
>useA : (a: A) => void
|
||||
|
||||
consume(b, b, useA); // consume<B, B>
|
||||
>consume(b, b, useA) : void
|
||||
>consume : <T, U extends T>(t: T, u: U, f: (x: T) => void) => void
|
||||
>b : B
|
||||
>b : B
|
||||
>useA : (a: A) => void
|
||||
|
||||
consume(c, c, useA); // consume<C, C>
|
||||
>consume(c, c, useA) : void
|
||||
>consume : <T, U extends T>(t: T, u: U, f: (x: T) => void) => void
|
||||
>c : C
|
||||
>c : C
|
||||
>useA : (a: A) => void
|
||||
}
|
||||
|
||||
// Repro from #52111
|
||||
|
||||
enum SyntaxKind {
|
||||
>SyntaxKind : SyntaxKind
|
||||
|
||||
Block,
|
||||
>Block : SyntaxKind.Block
|
||||
|
||||
Identifier,
|
||||
>Identifier : SyntaxKind.Identifier
|
||||
|
||||
CaseClause,
|
||||
>CaseClause : SyntaxKind.CaseClause
|
||||
|
||||
FunctionExpression,
|
||||
>FunctionExpression : SyntaxKind.FunctionExpression
|
||||
|
||||
FunctionDeclaration,
|
||||
>FunctionDeclaration : SyntaxKind.FunctionDeclaration
|
||||
}
|
||||
|
||||
interface Node { kind: SyntaxKind; }
|
||||
>kind : SyntaxKind
|
||||
|
||||
interface Expression extends Node { _expressionBrand: any; }
|
||||
>_expressionBrand : any
|
||||
|
||||
interface Declaration extends Node { _declarationBrand: any; }
|
||||
>_declarationBrand : any
|
||||
|
||||
interface Block extends Node { kind: SyntaxKind.Block; }
|
||||
>kind : SyntaxKind.Block
|
||||
>SyntaxKind : any
|
||||
|
||||
interface Identifier extends Expression, Declaration { kind: SyntaxKind.Identifier; }
|
||||
>kind : SyntaxKind.Identifier
|
||||
>SyntaxKind : any
|
||||
|
||||
interface CaseClause extends Node { kind: SyntaxKind.CaseClause; }
|
||||
>kind : SyntaxKind.CaseClause
|
||||
>SyntaxKind : any
|
||||
|
||||
interface FunctionDeclaration extends Declaration { kind: SyntaxKind.FunctionDeclaration; }
|
||||
>kind : SyntaxKind.FunctionDeclaration
|
||||
>SyntaxKind : any
|
||||
|
||||
type HasLocals = Block | FunctionDeclaration;
|
||||
>HasLocals : Block | FunctionDeclaration
|
||||
|
||||
declare function canHaveLocals(node: Node): node is HasLocals;
|
||||
>canHaveLocals : (node: Node) => node is HasLocals
|
||||
>node : Node
|
||||
|
||||
declare function assertNode<T extends Node, U extends T>(node: T | undefined, test: (node: T) => node is U): asserts node is U;
|
||||
>assertNode : { <T extends Node, U extends T>(node: T | undefined, test: (node: T) => node is U): asserts node is U; (node: Node | undefined, test: ((node: Node) => boolean) | undefined): void; }
|
||||
>node : T | undefined
|
||||
>test : (node: T) => node is U
|
||||
>node : T
|
||||
|
||||
declare function assertNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined): void;
|
||||
>assertNode : { <T extends Node, U extends T>(node: T | undefined, test: (node: T) => node is U): asserts node is U; (node: Node | undefined, test: ((node: Node) => boolean) | undefined): void; }
|
||||
>node : Node | undefined
|
||||
>test : ((node: Node) => boolean) | undefined
|
||||
>node : Node
|
||||
|
||||
function foo(node: FunctionDeclaration | CaseClause) {
|
||||
>foo : (node: FunctionDeclaration | CaseClause) => void
|
||||
>node : CaseClause | FunctionDeclaration
|
||||
|
||||
assertNode(node, canHaveLocals); // assertNode<Node, HasLocals>
|
||||
>assertNode(node, canHaveLocals) : void
|
||||
>assertNode : { <T extends Node, U extends T>(node: T | undefined, test: (node: T) => node is U): asserts node is U; (node: Node | undefined, test: ((node: Node) => boolean) | undefined): void; }
|
||||
>node : CaseClause | FunctionDeclaration
|
||||
>canHaveLocals : (node: Node) => node is HasLocals
|
||||
|
||||
node; // FunctionDeclaration
|
||||
>node : FunctionDeclaration
|
||||
}
|
||||
|
||||
declare function isExpression(node: Node): node is Expression;
|
||||
>isExpression : (node: Node) => node is Expression
|
||||
>node : Node
|
||||
|
||||
declare function tryCast<TOut extends TIn, TIn = any>(value: TIn | undefined, test: (value: TIn) => value is TOut): TOut;
|
||||
>tryCast : <TOut extends TIn, TIn = any>(value: TIn | undefined, test: (value: TIn) => value is TOut) => TOut
|
||||
>value : TIn | undefined
|
||||
>test : (value: TIn) => value is TOut
|
||||
>value : TIn
|
||||
|
||||
function bar(node: Identifier | FunctionDeclaration) {
|
||||
>bar : (node: Identifier | FunctionDeclaration) => void
|
||||
>node : Identifier | FunctionDeclaration
|
||||
|
||||
const a = tryCast(node, isExpression); // tryCast<Expression, Node>
|
||||
>a : Expression
|
||||
>tryCast(node, isExpression) : Expression
|
||||
>tryCast : <TOut extends TIn, TIn = any>(value: TIn | undefined, test: (value: TIn) => value is TOut) => TOut
|
||||
>node : Identifier | FunctionDeclaration
|
||||
>isExpression : (node: Node) => node is Expression
|
||||
}
|
||||
|
||||
// Repro from #49924
|
||||
|
||||
const enum SyntaxKind1 {
|
||||
>SyntaxKind1 : SyntaxKind1
|
||||
|
||||
ClassExpression,
|
||||
>ClassExpression : SyntaxKind1.ClassExpression
|
||||
|
||||
ClassStatement,
|
||||
>ClassStatement : SyntaxKind1.ClassStatement
|
||||
}
|
||||
|
||||
interface Node1 {
|
||||
kind: SyntaxKind1;
|
||||
>kind : SyntaxKind1
|
||||
}
|
||||
|
||||
interface Statement1 extends Node1 {
|
||||
_statementBrand: any;
|
||||
>_statementBrand : any
|
||||
}
|
||||
|
||||
interface ClassExpression1 extends Node1 {
|
||||
kind: SyntaxKind1.ClassExpression;
|
||||
>kind : SyntaxKind1.ClassExpression
|
||||
>SyntaxKind1 : any
|
||||
}
|
||||
|
||||
interface ClassStatement1 extends Statement1 {
|
||||
kind: SyntaxKind1.ClassStatement;
|
||||
>kind : SyntaxKind1.ClassStatement
|
||||
>SyntaxKind1 : any
|
||||
}
|
||||
|
||||
type ClassLike1 = ClassExpression1 | ClassStatement1;
|
||||
>ClassLike1 : ClassExpression1 | ClassStatement1
|
||||
|
||||
declare function isClassLike(node: Node1): node is ClassLike1;
|
||||
>isClassLike : (node: Node1) => node is ClassLike1
|
||||
>node : Node1
|
||||
|
||||
declare const statement: Statement1 | undefined;
|
||||
>statement : Statement1 | undefined
|
||||
|
||||
const maybeClassStatement = tryCast(statement, isClassLike); // ClassLike1
|
||||
>maybeClassStatement : ClassLike1
|
||||
>tryCast(statement, isClassLike) : ClassLike1
|
||||
>tryCast : <TOut extends TIn, TIn = any>(value: TIn | undefined, test: (value: TIn) => value is TOut) => TOut
|
||||
>statement : Statement1 | undefined
|
||||
>isClassLike : (node: Node1) => node is ClassLike1
|
||||
|
||||
// Repro from #49924
|
||||
|
||||
interface TypeNode extends Node {
|
||||
typeInfo: string;
|
||||
>typeInfo : string
|
||||
}
|
||||
|
||||
interface NodeArray<T extends Node> extends Array<T> {
|
||||
someProp: string;
|
||||
>someProp : string
|
||||
}
|
||||
|
||||
declare function isNodeArray<T extends Node>(array: readonly T[]): array is NodeArray<T>;
|
||||
>isNodeArray : <T extends Node>(array: readonly T[]) => array is NodeArray<T>
|
||||
>array : readonly T[]
|
||||
|
||||
declare const types: readonly TypeNode[];
|
||||
>types : readonly TypeNode[]
|
||||
|
||||
const x = tryCast(types, isNodeArray); // NodeAray<TypeNode>
|
||||
>x : NodeArray<TypeNode>
|
||||
>tryCast(types, isNodeArray) : NodeArray<TypeNode>
|
||||
>tryCast : <TOut extends TIn, TIn = any>(value: TIn | undefined, test: (value: TIn) => value is TOut) => TOut
|
||||
>types : readonly TypeNode[]
|
||||
>isNodeArray : <T extends Node>(array: readonly T[]) => array is NodeArray<T>
|
||||
|
||||
109
tests/cases/compiler/coAndContraVariantInferences2.ts
Normal file
109
tests/cases/compiler/coAndContraVariantInferences2.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
// @strict: true
|
||||
|
||||
interface A { a: string }
|
||||
interface B extends A { b: string }
|
||||
interface C extends A { c: string }
|
||||
|
||||
declare function cast<T, U extends T>(x: T, test: (x: T) => x is U): U;
|
||||
|
||||
declare function isC(x: A): x is C;
|
||||
|
||||
function f1(a: A, b: B) {
|
||||
const x1 = cast(a, isC); // cast<A, C>
|
||||
const x2 = cast(b, isC); // cast<A, C>
|
||||
}
|
||||
|
||||
declare function useA(a: A): void;
|
||||
|
||||
declare function consume<T, U extends T>(t: T, u: U, f: (x: T) => void): void;
|
||||
|
||||
function f2(b: B, c: C) {
|
||||
consume(b, c, useA); // consume<A, C>
|
||||
consume(c, b, useA); // consume<A, B>
|
||||
consume(b, b, useA); // consume<B, B>
|
||||
consume(c, c, useA); // consume<C, C>
|
||||
}
|
||||
|
||||
// Repro from #52111
|
||||
|
||||
enum SyntaxKind {
|
||||
Block,
|
||||
Identifier,
|
||||
CaseClause,
|
||||
FunctionExpression,
|
||||
FunctionDeclaration,
|
||||
}
|
||||
|
||||
interface Node { kind: SyntaxKind; }
|
||||
interface Expression extends Node { _expressionBrand: any; }
|
||||
interface Declaration extends Node { _declarationBrand: any; }
|
||||
interface Block extends Node { kind: SyntaxKind.Block; }
|
||||
interface Identifier extends Expression, Declaration { kind: SyntaxKind.Identifier; }
|
||||
interface CaseClause extends Node { kind: SyntaxKind.CaseClause; }
|
||||
interface FunctionDeclaration extends Declaration { kind: SyntaxKind.FunctionDeclaration; }
|
||||
|
||||
type HasLocals = Block | FunctionDeclaration;
|
||||
declare function canHaveLocals(node: Node): node is HasLocals;
|
||||
|
||||
declare function assertNode<T extends Node, U extends T>(node: T | undefined, test: (node: T) => node is U): asserts node is U;
|
||||
declare function assertNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined): void;
|
||||
|
||||
function foo(node: FunctionDeclaration | CaseClause) {
|
||||
assertNode(node, canHaveLocals); // assertNode<Node, HasLocals>
|
||||
node; // FunctionDeclaration
|
||||
}
|
||||
|
||||
declare function isExpression(node: Node): node is Expression;
|
||||
|
||||
declare function tryCast<TOut extends TIn, TIn = any>(value: TIn | undefined, test: (value: TIn) => value is TOut): TOut;
|
||||
|
||||
function bar(node: Identifier | FunctionDeclaration) {
|
||||
const a = tryCast(node, isExpression); // tryCast<Expression, Node>
|
||||
}
|
||||
|
||||
// Repro from #49924
|
||||
|
||||
const enum SyntaxKind1 {
|
||||
ClassExpression,
|
||||
ClassStatement,
|
||||
}
|
||||
|
||||
interface Node1 {
|
||||
kind: SyntaxKind1;
|
||||
}
|
||||
|
||||
interface Statement1 extends Node1 {
|
||||
_statementBrand: any;
|
||||
}
|
||||
|
||||
interface ClassExpression1 extends Node1 {
|
||||
kind: SyntaxKind1.ClassExpression;
|
||||
}
|
||||
|
||||
interface ClassStatement1 extends Statement1 {
|
||||
kind: SyntaxKind1.ClassStatement;
|
||||
}
|
||||
|
||||
type ClassLike1 = ClassExpression1 | ClassStatement1;
|
||||
|
||||
declare function isClassLike(node: Node1): node is ClassLike1;
|
||||
|
||||
declare const statement: Statement1 | undefined;
|
||||
|
||||
const maybeClassStatement = tryCast(statement, isClassLike); // ClassLike1
|
||||
|
||||
// Repro from #49924
|
||||
|
||||
interface TypeNode extends Node {
|
||||
typeInfo: string;
|
||||
}
|
||||
|
||||
interface NodeArray<T extends Node> extends Array<T> {
|
||||
someProp: string;
|
||||
}
|
||||
|
||||
declare function isNodeArray<T extends Node>(array: readonly T[]): array is NodeArray<T>;
|
||||
|
||||
declare const types: readonly TypeNode[];
|
||||
|
||||
const x = tryCast(types, isNodeArray); // NodeAray<TypeNode>
|
||||
Reference in New Issue
Block a user