|
| 1 | +//// [coAndContraVariantInferences2.ts] |
| 2 | +interface A { a: string } |
| 3 | +interface B extends A { b: string } |
| 4 | +interface C extends A { c: string } |
| 5 | + |
| 6 | +declare function cast<T, U extends T>(x: T, test: (x: T) => x is U): U; |
| 7 | + |
| 8 | +declare function isC(x: A): x is C; |
| 9 | + |
| 10 | +function f1(a: A, b: B) { |
| 11 | + const x1 = cast(a, isC); // cast<A, C> |
| 12 | + const x2 = cast(b, isC); // cast<A, C> |
| 13 | +} |
| 14 | + |
| 15 | +declare function useA(a: A): void; |
| 16 | + |
| 17 | +declare function consume<T, U extends T>(t: T, u: U, f: (x: T) => void): void; |
| 18 | + |
| 19 | +function f2(b: B, c: C) { |
| 20 | + consume(b, c, useA); // consume<A, C> |
| 21 | + consume(c, b, useA); // consume<A, B> |
| 22 | + consume(b, b, useA); // consume<B, B> |
| 23 | + consume(c, c, useA); // consume<C, C> |
| 24 | +} |
| 25 | + |
| 26 | +// Repro from #52111 |
| 27 | + |
| 28 | +enum SyntaxKind { |
| 29 | + Block, |
| 30 | + Identifier, |
| 31 | + CaseClause, |
| 32 | + FunctionExpression, |
| 33 | + FunctionDeclaration, |
| 34 | +} |
| 35 | + |
| 36 | +interface Node { kind: SyntaxKind; } |
| 37 | +interface Expression extends Node { _expressionBrand: any; } |
| 38 | +interface Declaration extends Node { _declarationBrand: any; } |
| 39 | +interface Block extends Node { kind: SyntaxKind.Block; } |
| 40 | +interface Identifier extends Expression, Declaration { kind: SyntaxKind.Identifier; } |
| 41 | +interface CaseClause extends Node { kind: SyntaxKind.CaseClause; } |
| 42 | +interface FunctionDeclaration extends Declaration { kind: SyntaxKind.FunctionDeclaration; } |
| 43 | + |
| 44 | +type HasLocals = Block | FunctionDeclaration; |
| 45 | +declare function canHaveLocals(node: Node): node is HasLocals; |
| 46 | + |
| 47 | +declare function assertNode<T extends Node, U extends T>(node: T | undefined, test: (node: T) => node is U): asserts node is U; |
| 48 | +declare function assertNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined): void; |
| 49 | + |
| 50 | +function foo(node: FunctionDeclaration | CaseClause) { |
| 51 | + assertNode(node, canHaveLocals); // assertNode<Node, HasLocals> |
| 52 | + node; // FunctionDeclaration |
| 53 | +} |
| 54 | + |
| 55 | +declare function isExpression(node: Node): node is Expression; |
| 56 | + |
| 57 | +declare function tryCast<TOut extends TIn, TIn = any>(value: TIn | undefined, test: (value: TIn) => value is TOut): TOut; |
| 58 | + |
| 59 | +function bar(node: Identifier | FunctionDeclaration) { |
| 60 | + const a = tryCast(node, isExpression); // tryCast<Expression, Node> |
| 61 | +} |
| 62 | + |
| 63 | +// Repro from #49924 |
| 64 | + |
| 65 | +const enum SyntaxKind1 { |
| 66 | + ClassExpression, |
| 67 | + ClassStatement, |
| 68 | +} |
| 69 | + |
| 70 | +interface Node1 { |
| 71 | + kind: SyntaxKind1; |
| 72 | +} |
| 73 | + |
| 74 | +interface Statement1 extends Node1 { |
| 75 | + _statementBrand: any; |
| 76 | +} |
| 77 | + |
| 78 | +interface ClassExpression1 extends Node1 { |
| 79 | + kind: SyntaxKind1.ClassExpression; |
| 80 | +} |
| 81 | + |
| 82 | +interface ClassStatement1 extends Statement1 { |
| 83 | + kind: SyntaxKind1.ClassStatement; |
| 84 | +} |
| 85 | + |
| 86 | +type ClassLike1 = ClassExpression1 | ClassStatement1; |
| 87 | + |
| 88 | +declare function isClassLike(node: Node1): node is ClassLike1; |
| 89 | + |
| 90 | +declare const statement: Statement1 | undefined; |
| 91 | + |
| 92 | +const maybeClassStatement = tryCast(statement, isClassLike); // ClassLike1 |
| 93 | + |
| 94 | +// Repro from #49924 |
| 95 | + |
| 96 | +interface TypeNode extends Node { |
| 97 | + typeInfo: string; |
| 98 | +} |
| 99 | + |
| 100 | +interface NodeArray<T extends Node> extends Array<T> { |
| 101 | + someProp: string; |
| 102 | +} |
| 103 | + |
| 104 | +declare function isNodeArray<T extends Node>(array: readonly T[]): array is NodeArray<T>; |
| 105 | + |
| 106 | +declare const types: readonly TypeNode[]; |
| 107 | + |
| 108 | +const x = tryCast(types, isNodeArray); // NodeAray<TypeNode> |
| 109 | + |
| 110 | + |
| 111 | +//// [coAndContraVariantInferences2.js] |
| 112 | +"use strict"; |
| 113 | +function f1(a, b) { |
| 114 | + var x1 = cast(a, isC); // cast<A, C> |
| 115 | + var x2 = cast(b, isC); // cast<A, C> |
| 116 | +} |
| 117 | +function f2(b, c) { |
| 118 | + consume(b, c, useA); // consume<A, C> |
| 119 | + consume(c, b, useA); // consume<A, B> |
| 120 | + consume(b, b, useA); // consume<B, B> |
| 121 | + consume(c, c, useA); // consume<C, C> |
| 122 | +} |
| 123 | +// Repro from #52111 |
| 124 | +var SyntaxKind; |
| 125 | +(function (SyntaxKind) { |
| 126 | + SyntaxKind[SyntaxKind["Block"] = 0] = "Block"; |
| 127 | + SyntaxKind[SyntaxKind["Identifier"] = 1] = "Identifier"; |
| 128 | + SyntaxKind[SyntaxKind["CaseClause"] = 2] = "CaseClause"; |
| 129 | + SyntaxKind[SyntaxKind["FunctionExpression"] = 3] = "FunctionExpression"; |
| 130 | + SyntaxKind[SyntaxKind["FunctionDeclaration"] = 4] = "FunctionDeclaration"; |
| 131 | +})(SyntaxKind || (SyntaxKind = {})); |
| 132 | +function foo(node) { |
| 133 | + assertNode(node, canHaveLocals); // assertNode<Node, HasLocals> |
| 134 | + node; // FunctionDeclaration |
| 135 | +} |
| 136 | +function bar(node) { |
| 137 | + var a = tryCast(node, isExpression); // tryCast<Expression, Node> |
| 138 | +} |
| 139 | +var maybeClassStatement = tryCast(statement, isClassLike); // ClassLike1 |
| 140 | +var x = tryCast(types, isNodeArray); // NodeAray<TypeNode> |
0 commit comments