Merge pull request #33678 from microsoft/fix33617
Property handle recursive type references in type inference
This commit is contained in:
commit
7ce793c5b8
|
@ -17070,7 +17070,7 @@ namespace ts {
|
|||
function couldContainTypeVariables(type: Type): boolean {
|
||||
const objectFlags = getObjectFlags(type);
|
||||
return !!(type.flags & TypeFlags.Instantiable ||
|
||||
objectFlags & ObjectFlags.Reference && forEach(getTypeArguments(<TypeReference>type), couldContainTypeVariables) ||
|
||||
objectFlags & ObjectFlags.Reference && ((<TypeReference>type).node || forEach(getTypeArguments(<TypeReference>type), couldContainTypeVariables)) ||
|
||||
objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && type.symbol.declarations ||
|
||||
objectFlags & ObjectFlags.Mapped ||
|
||||
type.flags & TypeFlags.UnionOrIntersection && !(type.flags & TypeFlags.EnumLiteral) && couldUnionOrIntersectionContainTypeVariables(<UnionOrIntersectionType>type));
|
||||
|
@ -17367,7 +17367,8 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (
|
||||
(<TypeReference>source).target === (<TypeReference>target).target || isArrayType(source) && isArrayType(target))) {
|
||||
(<TypeReference>source).target === (<TypeReference>target).target || isArrayType(source) && isArrayType(target)) &&
|
||||
!((<TypeReference>source).node && (<TypeReference>target).node)) {
|
||||
// If source and target are references to the same generic type, infer from type arguments
|
||||
inferFromTypeArguments(getTypeArguments(<TypeReference>source), getTypeArguments(<TypeReference>target), getVariances((<TypeReference>source).target));
|
||||
}
|
||||
|
@ -17648,6 +17649,12 @@ namespace ts {
|
|||
}
|
||||
|
||||
function inferFromObjectTypesWorker(source: Type, target: Type) {
|
||||
if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (
|
||||
(<TypeReference>source).target === (<TypeReference>target).target || isArrayType(source) && isArrayType(target))) {
|
||||
// If source and target are references to the same generic type, infer from type arguments
|
||||
inferFromTypeArguments(getTypeArguments(<TypeReference>source), getTypeArguments(<TypeReference>target), getVariances((<TypeReference>source).target));
|
||||
return;
|
||||
}
|
||||
if (isGenericMappedType(source) && isGenericMappedType(target)) {
|
||||
// The source and target types are generic types { [P in S]: X } and { [P in T]: Y }, so we infer
|
||||
// from S to T and from X to Y.
|
||||
|
|
|
@ -2,9 +2,18 @@ tests/cases/conformance/types/typeRelationships/recursiveTypes/recursiveTypeRefe
|
|||
tests/cases/conformance/types/typeRelationships/recursiveTypes/recursiveTypeReferences1.ts(60,7): error TS2322: Type 'number' is not assignable to type 'string | RecArray<string>'.
|
||||
tests/cases/conformance/types/typeRelationships/recursiveTypes/recursiveTypeReferences1.ts(66,8): error TS2322: Type 'number' is not assignable to type 'string | string[]'.
|
||||
tests/cases/conformance/types/typeRelationships/recursiveTypes/recursiveTypeReferences1.ts(72,8): error TS2322: Type 'number' is not assignable to type 'string | (string | string[])[]'.
|
||||
tests/cases/conformance/types/typeRelationships/recursiveTypes/recursiveTypeReferences1.ts(102,10): error TS2304: Cannot find name 'html'.
|
||||
tests/cases/conformance/types/typeRelationships/recursiveTypes/recursiveTypeReferences1.ts(104,12): error TS2304: Cannot find name 'html'.
|
||||
tests/cases/conformance/types/typeRelationships/recursiveTypes/recursiveTypeReferences1.ts(105,7): error TS2304: Cannot find name 'html'.
|
||||
tests/cases/conformance/types/typeRelationships/recursiveTypes/recursiveTypeReferences1.ts(106,52): error TS2304: Cannot find name 'frag'.
|
||||
tests/cases/conformance/types/typeRelationships/recursiveTypes/recursiveTypeReferences1.ts(116,11): error TS2304: Cannot find name 'concat'.
|
||||
tests/cases/conformance/types/typeRelationships/recursiveTypes/recursiveTypeReferences1.ts(116,24): error TS2304: Cannot find name 'concat'.
|
||||
tests/cases/conformance/types/typeRelationships/recursiveTypes/recursiveTypeReferences1.ts(117,11): error TS2304: Cannot find name 'concat'.
|
||||
tests/cases/conformance/types/typeRelationships/recursiveTypes/recursiveTypeReferences1.ts(122,11): error TS2304: Cannot find name 'concat'.
|
||||
tests/cases/conformance/types/typeRelationships/recursiveTypes/recursiveTypeReferences1.ts(127,3): error TS2304: Cannot find name 'assert'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/typeRelationships/recursiveTypes/recursiveTypeReferences1.ts (4 errors) ====
|
||||
==== tests/cases/conformance/types/typeRelationships/recursiveTypes/recursiveTypeReferences1.ts (13 errors) ====
|
||||
type ValueOrArray<T> = T | Array<ValueOrArray<T>>;
|
||||
|
||||
const a0: ValueOrArray<number> = 1;
|
||||
|
@ -92,4 +101,72 @@ tests/cases/conformance/types/typeRelationships/recursiveTypes/recursiveTypeRefe
|
|||
type T13 = T13[] | string;
|
||||
type T14 = T14[] & { x: string };
|
||||
type T15<X> = X extends string ? T15<X>[] : never;
|
||||
|
||||
type ValueOrArray1<T> = T | ValueOrArray1<T>[];
|
||||
type ValueOrArray2<T> = T | ValueOrArray2<T>[];
|
||||
|
||||
declare function foo1<T>(a: ValueOrArray1<T>): T;
|
||||
declare let ra1: ValueOrArray2<string>;
|
||||
|
||||
let x1 = foo1(ra1); // Boom!
|
||||
|
||||
type NumberOrArray1<T> = T | ValueOrArray1<T>[];
|
||||
type NumberOrArray2<T> = T | ValueOrArray2<T>[];
|
||||
|
||||
declare function foo2<T>(a: ValueOrArray1<T>): T;
|
||||
declare let ra2: ValueOrArray2<string>;
|
||||
|
||||
let x2 = foo2(ra2); // Boom!
|
||||
|
||||
// Repro from #33617 (errors are expected)
|
||||
|
||||
type Tree = [HTMLHeadingElement, Tree][];
|
||||
|
||||
function parse(node: Tree, index: number[] = []): HTMLUListElement {
|
||||
return html('ul', node.map(([el, children], i) => {
|
||||
~~~~
|
||||
!!! error TS2304: Cannot find name 'html'.
|
||||
const idx = [...index, i + 1];
|
||||
return html('li', [
|
||||
~~~~
|
||||
!!! error TS2304: Cannot find name 'html'.
|
||||
html('a', { href: `#${el.id}`, rel: 'noopener', 'data-index': idx.join('.') }, el.textContent!),
|
||||
~~~~
|
||||
!!! error TS2304: Cannot find name 'html'.
|
||||
children.length > 0 ? parse(children, idx) : frag()
|
||||
~~~~
|
||||
!!! error TS2304: Cannot find name 'frag'.
|
||||
]);
|
||||
}));
|
||||
}
|
||||
|
||||
function cons(hs: HTMLHeadingElement[]): Tree {
|
||||
return hs
|
||||
.reduce<HTMLHeadingElement[][]>((hss, h) => {
|
||||
const hs = hss.pop()!;
|
||||
return hs.length === 0 || level(h) > level(hs[0])
|
||||
? concat(hss, [concat(hs, [h])])
|
||||
~~~~~~
|
||||
!!! error TS2304: Cannot find name 'concat'.
|
||||
~~~~~~
|
||||
!!! error TS2304: Cannot find name 'concat'.
|
||||
: concat(hss, [hs, [h]]);
|
||||
~~~~~~
|
||||
!!! error TS2304: Cannot find name 'concat'.
|
||||
}, [[]])
|
||||
.reduce<Tree>((node, hs) =>
|
||||
hs.length === 0
|
||||
? node
|
||||
: concat<Tree[number]>(node, [[hs.shift()!, cons(hs)]])
|
||||
~~~~~~
|
||||
!!! error TS2304: Cannot find name 'concat'.
|
||||
, []);
|
||||
}
|
||||
|
||||
function level(h: HTMLHeadingElement): number {
|
||||
assert(isFinite(+h.tagName[1]));
|
||||
~~~~~~
|
||||
!!! error TS2304: Cannot find name 'assert'.
|
||||
return +h.tagName[1];
|
||||
}
|
||||
|
|
@ -78,10 +78,67 @@ type T12 = (T12)[];
|
|||
type T13 = T13[] | string;
|
||||
type T14 = T14[] & { x: string };
|
||||
type T15<X> = X extends string ? T15<X>[] : never;
|
||||
|
||||
type ValueOrArray1<T> = T | ValueOrArray1<T>[];
|
||||
type ValueOrArray2<T> = T | ValueOrArray2<T>[];
|
||||
|
||||
declare function foo1<T>(a: ValueOrArray1<T>): T;
|
||||
declare let ra1: ValueOrArray2<string>;
|
||||
|
||||
let x1 = foo1(ra1); // Boom!
|
||||
|
||||
type NumberOrArray1<T> = T | ValueOrArray1<T>[];
|
||||
type NumberOrArray2<T> = T | ValueOrArray2<T>[];
|
||||
|
||||
declare function foo2<T>(a: ValueOrArray1<T>): T;
|
||||
declare let ra2: ValueOrArray2<string>;
|
||||
|
||||
let x2 = foo2(ra2); // Boom!
|
||||
|
||||
// Repro from #33617 (errors are expected)
|
||||
|
||||
type Tree = [HTMLHeadingElement, Tree][];
|
||||
|
||||
function parse(node: Tree, index: number[] = []): HTMLUListElement {
|
||||
return html('ul', node.map(([el, children], i) => {
|
||||
const idx = [...index, i + 1];
|
||||
return html('li', [
|
||||
html('a', { href: `#${el.id}`, rel: 'noopener', 'data-index': idx.join('.') }, el.textContent!),
|
||||
children.length > 0 ? parse(children, idx) : frag()
|
||||
]);
|
||||
}));
|
||||
}
|
||||
|
||||
function cons(hs: HTMLHeadingElement[]): Tree {
|
||||
return hs
|
||||
.reduce<HTMLHeadingElement[][]>((hss, h) => {
|
||||
const hs = hss.pop()!;
|
||||
return hs.length === 0 || level(h) > level(hs[0])
|
||||
? concat(hss, [concat(hs, [h])])
|
||||
: concat(hss, [hs, [h]]);
|
||||
}, [[]])
|
||||
.reduce<Tree>((node, hs) =>
|
||||
hs.length === 0
|
||||
? node
|
||||
: concat<Tree[number]>(node, [[hs.shift()!, cons(hs)]])
|
||||
, []);
|
||||
}
|
||||
|
||||
function level(h: HTMLHeadingElement): number {
|
||||
assert(isFinite(+h.tagName[1]));
|
||||
return +h.tagName[1];
|
||||
}
|
||||
|
||||
|
||||
//// [recursiveTypeReferences1.js]
|
||||
"use strict";
|
||||
var __spreadArrays = (this && this.__spreadArrays) || function () {
|
||||
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
|
||||
for (var r = Array(s), k = 0, i = 0; i < il; i++)
|
||||
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
|
||||
r[k] = a[j];
|
||||
return r;
|
||||
};
|
||||
var a0 = 1;
|
||||
var a1 = [1, [2, 3], [4, [5, [6, 7]]]];
|
||||
var hypertextNode = ["div", { id: "parent" },
|
||||
|
@ -124,6 +181,37 @@ flat2([[[0]]]); // number[]
|
|||
flat2([1, 'a', [2]]); // (string | number)[]
|
||||
flat2([1, [2, 'a']]); // (string | number)[]
|
||||
flat2([1, ['a']]); // Error
|
||||
var x1 = foo1(ra1); // Boom!
|
||||
var x2 = foo2(ra2); // Boom!
|
||||
function parse(node, index) {
|
||||
if (index === void 0) { index = []; }
|
||||
return html('ul', node.map(function (_a, i) {
|
||||
var el = _a[0], children = _a[1];
|
||||
var idx = __spreadArrays(index, [i + 1]);
|
||||
return html('li', [
|
||||
html('a', { href: "#" + el.id, rel: 'noopener', 'data-index': idx.join('.') }, el.textContent),
|
||||
children.length > 0 ? parse(children, idx) : frag()
|
||||
]);
|
||||
}));
|
||||
}
|
||||
function cons(hs) {
|
||||
return hs
|
||||
.reduce(function (hss, h) {
|
||||
var hs = hss.pop();
|
||||
return hs.length === 0 || level(h) > level(hs[0])
|
||||
? concat(hss, [concat(hs, [h])])
|
||||
: concat(hss, [hs, [h]]);
|
||||
}, [[]])
|
||||
.reduce(function (node, hs) {
|
||||
return hs.length === 0
|
||||
? node
|
||||
: concat(node, [[hs.shift(), cons(hs)]]);
|
||||
}, []);
|
||||
}
|
||||
function level(h) {
|
||||
assert(isFinite(+h.tagName[1]));
|
||||
return +h.tagName[1];
|
||||
}
|
||||
|
||||
|
||||
//// [recursiveTypeReferences1.d.ts]
|
||||
|
@ -165,3 +253,17 @@ declare type T14 = T14[] & {
|
|||
x: string;
|
||||
};
|
||||
declare type T15<X> = X extends string ? T15<X>[] : never;
|
||||
declare type ValueOrArray1<T> = T | ValueOrArray1<T>[];
|
||||
declare type ValueOrArray2<T> = T | ValueOrArray2<T>[];
|
||||
declare function foo1<T>(a: ValueOrArray1<T>): T;
|
||||
declare let ra1: ValueOrArray2<string>;
|
||||
declare let x1: string;
|
||||
declare type NumberOrArray1<T> = T | ValueOrArray1<T>[];
|
||||
declare type NumberOrArray2<T> = T | ValueOrArray2<T>[];
|
||||
declare function foo2<T>(a: ValueOrArray1<T>): T;
|
||||
declare let ra2: ValueOrArray2<string>;
|
||||
declare let x2: string;
|
||||
declare type Tree = [HTMLHeadingElement, Tree][];
|
||||
declare function parse(node: Tree, index?: number[]): HTMLUListElement;
|
||||
declare function cons(hs: HTMLHeadingElement[]): Tree;
|
||||
declare function level(h: HTMLHeadingElement): number;
|
||||
|
|
|
@ -275,3 +275,205 @@ type T15<X> = X extends string ? T15<X>[] : never;
|
|||
>T15 : Symbol(T15, Decl(recursiveTypeReferences1.ts, 77, 33))
|
||||
>X : Symbol(X, Decl(recursiveTypeReferences1.ts, 78, 9))
|
||||
|
||||
type ValueOrArray1<T> = T | ValueOrArray1<T>[];
|
||||
>ValueOrArray1 : Symbol(ValueOrArray1, Decl(recursiveTypeReferences1.ts, 78, 50))
|
||||
>T : Symbol(T, Decl(recursiveTypeReferences1.ts, 80, 19))
|
||||
>T : Symbol(T, Decl(recursiveTypeReferences1.ts, 80, 19))
|
||||
>ValueOrArray1 : Symbol(ValueOrArray1, Decl(recursiveTypeReferences1.ts, 78, 50))
|
||||
>T : Symbol(T, Decl(recursiveTypeReferences1.ts, 80, 19))
|
||||
|
||||
type ValueOrArray2<T> = T | ValueOrArray2<T>[];
|
||||
>ValueOrArray2 : Symbol(ValueOrArray2, Decl(recursiveTypeReferences1.ts, 80, 47))
|
||||
>T : Symbol(T, Decl(recursiveTypeReferences1.ts, 81, 19))
|
||||
>T : Symbol(T, Decl(recursiveTypeReferences1.ts, 81, 19))
|
||||
>ValueOrArray2 : Symbol(ValueOrArray2, Decl(recursiveTypeReferences1.ts, 80, 47))
|
||||
>T : Symbol(T, Decl(recursiveTypeReferences1.ts, 81, 19))
|
||||
|
||||
declare function foo1<T>(a: ValueOrArray1<T>): T;
|
||||
>foo1 : Symbol(foo1, Decl(recursiveTypeReferences1.ts, 81, 47))
|
||||
>T : Symbol(T, Decl(recursiveTypeReferences1.ts, 83, 22))
|
||||
>a : Symbol(a, Decl(recursiveTypeReferences1.ts, 83, 25))
|
||||
>ValueOrArray1 : Symbol(ValueOrArray1, Decl(recursiveTypeReferences1.ts, 78, 50))
|
||||
>T : Symbol(T, Decl(recursiveTypeReferences1.ts, 83, 22))
|
||||
>T : Symbol(T, Decl(recursiveTypeReferences1.ts, 83, 22))
|
||||
|
||||
declare let ra1: ValueOrArray2<string>;
|
||||
>ra1 : Symbol(ra1, Decl(recursiveTypeReferences1.ts, 84, 11))
|
||||
>ValueOrArray2 : Symbol(ValueOrArray2, Decl(recursiveTypeReferences1.ts, 80, 47))
|
||||
|
||||
let x1 = foo1(ra1); // Boom!
|
||||
>x1 : Symbol(x1, Decl(recursiveTypeReferences1.ts, 86, 3))
|
||||
>foo1 : Symbol(foo1, Decl(recursiveTypeReferences1.ts, 81, 47))
|
||||
>ra1 : Symbol(ra1, Decl(recursiveTypeReferences1.ts, 84, 11))
|
||||
|
||||
type NumberOrArray1<T> = T | ValueOrArray1<T>[];
|
||||
>NumberOrArray1 : Symbol(NumberOrArray1, Decl(recursiveTypeReferences1.ts, 86, 19))
|
||||
>T : Symbol(T, Decl(recursiveTypeReferences1.ts, 88, 20))
|
||||
>T : Symbol(T, Decl(recursiveTypeReferences1.ts, 88, 20))
|
||||
>ValueOrArray1 : Symbol(ValueOrArray1, Decl(recursiveTypeReferences1.ts, 78, 50))
|
||||
>T : Symbol(T, Decl(recursiveTypeReferences1.ts, 88, 20))
|
||||
|
||||
type NumberOrArray2<T> = T | ValueOrArray2<T>[];
|
||||
>NumberOrArray2 : Symbol(NumberOrArray2, Decl(recursiveTypeReferences1.ts, 88, 48))
|
||||
>T : Symbol(T, Decl(recursiveTypeReferences1.ts, 89, 20))
|
||||
>T : Symbol(T, Decl(recursiveTypeReferences1.ts, 89, 20))
|
||||
>ValueOrArray2 : Symbol(ValueOrArray2, Decl(recursiveTypeReferences1.ts, 80, 47))
|
||||
>T : Symbol(T, Decl(recursiveTypeReferences1.ts, 89, 20))
|
||||
|
||||
declare function foo2<T>(a: ValueOrArray1<T>): T;
|
||||
>foo2 : Symbol(foo2, Decl(recursiveTypeReferences1.ts, 89, 48))
|
||||
>T : Symbol(T, Decl(recursiveTypeReferences1.ts, 91, 22))
|
||||
>a : Symbol(a, Decl(recursiveTypeReferences1.ts, 91, 25))
|
||||
>ValueOrArray1 : Symbol(ValueOrArray1, Decl(recursiveTypeReferences1.ts, 78, 50))
|
||||
>T : Symbol(T, Decl(recursiveTypeReferences1.ts, 91, 22))
|
||||
>T : Symbol(T, Decl(recursiveTypeReferences1.ts, 91, 22))
|
||||
|
||||
declare let ra2: ValueOrArray2<string>;
|
||||
>ra2 : Symbol(ra2, Decl(recursiveTypeReferences1.ts, 92, 11))
|
||||
>ValueOrArray2 : Symbol(ValueOrArray2, Decl(recursiveTypeReferences1.ts, 80, 47))
|
||||
|
||||
let x2 = foo2(ra2); // Boom!
|
||||
>x2 : Symbol(x2, Decl(recursiveTypeReferences1.ts, 94, 3))
|
||||
>foo2 : Symbol(foo2, Decl(recursiveTypeReferences1.ts, 89, 48))
|
||||
>ra2 : Symbol(ra2, Decl(recursiveTypeReferences1.ts, 92, 11))
|
||||
|
||||
// Repro from #33617 (errors are expected)
|
||||
|
||||
type Tree = [HTMLHeadingElement, Tree][];
|
||||
>Tree : Symbol(Tree, Decl(recursiveTypeReferences1.ts, 94, 19))
|
||||
>HTMLHeadingElement : Symbol(HTMLHeadingElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
|
||||
>Tree : Symbol(Tree, Decl(recursiveTypeReferences1.ts, 94, 19))
|
||||
|
||||
function parse(node: Tree, index: number[] = []): HTMLUListElement {
|
||||
>parse : Symbol(parse, Decl(recursiveTypeReferences1.ts, 98, 41))
|
||||
>node : Symbol(node, Decl(recursiveTypeReferences1.ts, 100, 15))
|
||||
>Tree : Symbol(Tree, Decl(recursiveTypeReferences1.ts, 94, 19))
|
||||
>index : Symbol(index, Decl(recursiveTypeReferences1.ts, 100, 26))
|
||||
>HTMLUListElement : Symbol(HTMLUListElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
|
||||
|
||||
return html('ul', node.map(([el, children], i) => {
|
||||
>node.map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --))
|
||||
>node : Symbol(node, Decl(recursiveTypeReferences1.ts, 100, 15))
|
||||
>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --))
|
||||
>el : Symbol(el, Decl(recursiveTypeReferences1.ts, 101, 31))
|
||||
>children : Symbol(children, Decl(recursiveTypeReferences1.ts, 101, 34))
|
||||
>i : Symbol(i, Decl(recursiveTypeReferences1.ts, 101, 45))
|
||||
|
||||
const idx = [...index, i + 1];
|
||||
>idx : Symbol(idx, Decl(recursiveTypeReferences1.ts, 102, 9))
|
||||
>index : Symbol(index, Decl(recursiveTypeReferences1.ts, 100, 26))
|
||||
>i : Symbol(i, Decl(recursiveTypeReferences1.ts, 101, 45))
|
||||
|
||||
return html('li', [
|
||||
html('a', { href: `#${el.id}`, rel: 'noopener', 'data-index': idx.join('.') }, el.textContent!),
|
||||
>href : Symbol(href, Decl(recursiveTypeReferences1.ts, 104, 17))
|
||||
>el.id : Symbol(Element.id, Decl(lib.dom.d.ts, --, --))
|
||||
>el : Symbol(el, Decl(recursiveTypeReferences1.ts, 101, 31))
|
||||
>id : Symbol(Element.id, Decl(lib.dom.d.ts, --, --))
|
||||
>rel : Symbol(rel, Decl(recursiveTypeReferences1.ts, 104, 36))
|
||||
>'data-index' : Symbol('data-index', Decl(recursiveTypeReferences1.ts, 104, 53))
|
||||
>idx.join : Symbol(Array.join, Decl(lib.es5.d.ts, --, --))
|
||||
>idx : Symbol(idx, Decl(recursiveTypeReferences1.ts, 102, 9))
|
||||
>join : Symbol(Array.join, Decl(lib.es5.d.ts, --, --))
|
||||
>el.textContent : Symbol(Node.textContent, Decl(lib.dom.d.ts, --, --))
|
||||
>el : Symbol(el, Decl(recursiveTypeReferences1.ts, 101, 31))
|
||||
>textContent : Symbol(Node.textContent, Decl(lib.dom.d.ts, --, --))
|
||||
|
||||
children.length > 0 ? parse(children, idx) : frag()
|
||||
>children.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
|
||||
>children : Symbol(children, Decl(recursiveTypeReferences1.ts, 101, 34))
|
||||
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
|
||||
>parse : Symbol(parse, Decl(recursiveTypeReferences1.ts, 98, 41))
|
||||
>children : Symbol(children, Decl(recursiveTypeReferences1.ts, 101, 34))
|
||||
>idx : Symbol(idx, Decl(recursiveTypeReferences1.ts, 102, 9))
|
||||
|
||||
]);
|
||||
}));
|
||||
}
|
||||
|
||||
function cons(hs: HTMLHeadingElement[]): Tree {
|
||||
>cons : Symbol(cons, Decl(recursiveTypeReferences1.ts, 108, 1))
|
||||
>hs : Symbol(hs, Decl(recursiveTypeReferences1.ts, 110, 14))
|
||||
>HTMLHeadingElement : Symbol(HTMLHeadingElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
|
||||
>Tree : Symbol(Tree, Decl(recursiveTypeReferences1.ts, 94, 19))
|
||||
|
||||
return hs
|
||||
>hs .reduce<HTMLHeadingElement[][]>((hss, h) => { const hs = hss.pop()!; return hs.length === 0 || level(h) > level(hs[0]) ? concat(hss, [concat(hs, [h])]) : concat(hss, [hs, [h]]); }, [[]]) .reduce : Symbol(Array.reduce, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>hs .reduce : Symbol(Array.reduce, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>hs : Symbol(hs, Decl(recursiveTypeReferences1.ts, 110, 14))
|
||||
|
||||
.reduce<HTMLHeadingElement[][]>((hss, h) => {
|
||||
>reduce : Symbol(Array.reduce, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>HTMLHeadingElement : Symbol(HTMLHeadingElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
|
||||
>hss : Symbol(hss, Decl(recursiveTypeReferences1.ts, 112, 37))
|
||||
>h : Symbol(h, Decl(recursiveTypeReferences1.ts, 112, 41))
|
||||
|
||||
const hs = hss.pop()!;
|
||||
>hs : Symbol(hs, Decl(recursiveTypeReferences1.ts, 113, 11))
|
||||
>hss.pop : Symbol(Array.pop, Decl(lib.es5.d.ts, --, --))
|
||||
>hss : Symbol(hss, Decl(recursiveTypeReferences1.ts, 112, 37))
|
||||
>pop : Symbol(Array.pop, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
return hs.length === 0 || level(h) > level(hs[0])
|
||||
>hs.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
|
||||
>hs : Symbol(hs, Decl(recursiveTypeReferences1.ts, 113, 11))
|
||||
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
|
||||
>level : Symbol(level, Decl(recursiveTypeReferences1.ts, 123, 1))
|
||||
>h : Symbol(h, Decl(recursiveTypeReferences1.ts, 112, 41))
|
||||
>level : Symbol(level, Decl(recursiveTypeReferences1.ts, 123, 1))
|
||||
>hs : Symbol(hs, Decl(recursiveTypeReferences1.ts, 113, 11))
|
||||
|
||||
? concat(hss, [concat(hs, [h])])
|
||||
>hss : Symbol(hss, Decl(recursiveTypeReferences1.ts, 112, 37))
|
||||
>hs : Symbol(hs, Decl(recursiveTypeReferences1.ts, 113, 11))
|
||||
>h : Symbol(h, Decl(recursiveTypeReferences1.ts, 112, 41))
|
||||
|
||||
: concat(hss, [hs, [h]]);
|
||||
>hss : Symbol(hss, Decl(recursiveTypeReferences1.ts, 112, 37))
|
||||
>hs : Symbol(hs, Decl(recursiveTypeReferences1.ts, 113, 11))
|
||||
>h : Symbol(h, Decl(recursiveTypeReferences1.ts, 112, 41))
|
||||
|
||||
}, [[]])
|
||||
.reduce<Tree>((node, hs) =>
|
||||
>reduce : Symbol(Array.reduce, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>Tree : Symbol(Tree, Decl(recursiveTypeReferences1.ts, 94, 19))
|
||||
>node : Symbol(node, Decl(recursiveTypeReferences1.ts, 118, 19))
|
||||
>hs : Symbol(hs, Decl(recursiveTypeReferences1.ts, 118, 24))
|
||||
|
||||
hs.length === 0
|
||||
>hs.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
|
||||
>hs : Symbol(hs, Decl(recursiveTypeReferences1.ts, 118, 24))
|
||||
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
? node
|
||||
>node : Symbol(node, Decl(recursiveTypeReferences1.ts, 118, 19))
|
||||
|
||||
: concat<Tree[number]>(node, [[hs.shift()!, cons(hs)]])
|
||||
>Tree : Symbol(Tree, Decl(recursiveTypeReferences1.ts, 94, 19))
|
||||
>node : Symbol(node, Decl(recursiveTypeReferences1.ts, 118, 19))
|
||||
>hs.shift : Symbol(Array.shift, Decl(lib.es5.d.ts, --, --))
|
||||
>hs : Symbol(hs, Decl(recursiveTypeReferences1.ts, 118, 24))
|
||||
>shift : Symbol(Array.shift, Decl(lib.es5.d.ts, --, --))
|
||||
>cons : Symbol(cons, Decl(recursiveTypeReferences1.ts, 108, 1))
|
||||
>hs : Symbol(hs, Decl(recursiveTypeReferences1.ts, 118, 24))
|
||||
|
||||
, []);
|
||||
}
|
||||
|
||||
function level(h: HTMLHeadingElement): number {
|
||||
>level : Symbol(level, Decl(recursiveTypeReferences1.ts, 123, 1))
|
||||
>h : Symbol(h, Decl(recursiveTypeReferences1.ts, 125, 15))
|
||||
>HTMLHeadingElement : Symbol(HTMLHeadingElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
|
||||
|
||||
assert(isFinite(+h.tagName[1]));
|
||||
>isFinite : Symbol(isFinite, Decl(lib.es5.d.ts, --, --))
|
||||
>h.tagName : Symbol(Element.tagName, Decl(lib.dom.d.ts, --, --))
|
||||
>h : Symbol(h, Decl(recursiveTypeReferences1.ts, 125, 15))
|
||||
>tagName : Symbol(Element.tagName, Decl(lib.dom.d.ts, --, --))
|
||||
|
||||
return +h.tagName[1];
|
||||
>h.tagName : Symbol(Element.tagName, Decl(lib.dom.d.ts, --, --))
|
||||
>h : Symbol(h, Decl(recursiveTypeReferences1.ts, 125, 15))
|
||||
>tagName : Symbol(Element.tagName, Decl(lib.dom.d.ts, --, --))
|
||||
}
|
||||
|
||||
|
|
|
@ -362,3 +362,249 @@ type T14 = T14[] & { x: string };
|
|||
type T15<X> = X extends string ? T15<X>[] : never;
|
||||
>T15 : T15<X>
|
||||
|
||||
type ValueOrArray1<T> = T | ValueOrArray1<T>[];
|
||||
>ValueOrArray1 : ValueOrArray1<T>
|
||||
|
||||
type ValueOrArray2<T> = T | ValueOrArray2<T>[];
|
||||
>ValueOrArray2 : ValueOrArray2<T>
|
||||
|
||||
declare function foo1<T>(a: ValueOrArray1<T>): T;
|
||||
>foo1 : <T>(a: ValueOrArray1<T>) => T
|
||||
>a : ValueOrArray1<T>
|
||||
|
||||
declare let ra1: ValueOrArray2<string>;
|
||||
>ra1 : ValueOrArray2<string>
|
||||
|
||||
let x1 = foo1(ra1); // Boom!
|
||||
>x1 : string
|
||||
>foo1(ra1) : string
|
||||
>foo1 : <T>(a: ValueOrArray1<T>) => T
|
||||
>ra1 : ValueOrArray2<string>
|
||||
|
||||
type NumberOrArray1<T> = T | ValueOrArray1<T>[];
|
||||
>NumberOrArray1 : NumberOrArray1<T>
|
||||
|
||||
type NumberOrArray2<T> = T | ValueOrArray2<T>[];
|
||||
>NumberOrArray2 : NumberOrArray2<T>
|
||||
|
||||
declare function foo2<T>(a: ValueOrArray1<T>): T;
|
||||
>foo2 : <T>(a: ValueOrArray1<T>) => T
|
||||
>a : ValueOrArray1<T>
|
||||
|
||||
declare let ra2: ValueOrArray2<string>;
|
||||
>ra2 : ValueOrArray2<string>
|
||||
|
||||
let x2 = foo2(ra2); // Boom!
|
||||
>x2 : string
|
||||
>foo2(ra2) : string
|
||||
>foo2 : <T>(a: ValueOrArray1<T>) => T
|
||||
>ra2 : ValueOrArray2<string>
|
||||
|
||||
// Repro from #33617 (errors are expected)
|
||||
|
||||
type Tree = [HTMLHeadingElement, Tree][];
|
||||
>Tree : Tree
|
||||
|
||||
function parse(node: Tree, index: number[] = []): HTMLUListElement {
|
||||
>parse : (node: Tree, index?: number[]) => HTMLUListElement
|
||||
>node : Tree
|
||||
>index : number[]
|
||||
>[] : never[]
|
||||
|
||||
return html('ul', node.map(([el, children], i) => {
|
||||
>html('ul', node.map(([el, children], i) => { const idx = [...index, i + 1]; return html('li', [ html('a', { href: `#${el.id}`, rel: 'noopener', 'data-index': idx.join('.') }, el.textContent!), children.length > 0 ? parse(children, idx) : frag() ]); })) : any
|
||||
>html : any
|
||||
>'ul' : "ul"
|
||||
>node.map(([el, children], i) => { const idx = [...index, i + 1]; return html('li', [ html('a', { href: `#${el.id}`, rel: 'noopener', 'data-index': idx.join('.') }, el.textContent!), children.length > 0 ? parse(children, idx) : frag() ]); }) : any[]
|
||||
>node.map : <U>(callbackfn: (value: [HTMLHeadingElement, Tree], index: number, array: [HTMLHeadingElement, Tree][]) => U, thisArg?: any) => U[]
|
||||
>node : Tree
|
||||
>map : <U>(callbackfn: (value: [HTMLHeadingElement, Tree], index: number, array: [HTMLHeadingElement, Tree][]) => U, thisArg?: any) => U[]
|
||||
>([el, children], i) => { const idx = [...index, i + 1]; return html('li', [ html('a', { href: `#${el.id}`, rel: 'noopener', 'data-index': idx.join('.') }, el.textContent!), children.length > 0 ? parse(children, idx) : frag() ]); } : ([el, children]: [HTMLHeadingElement, Tree], i: number) => any
|
||||
>el : HTMLHeadingElement
|
||||
>children : Tree
|
||||
>i : number
|
||||
|
||||
const idx = [...index, i + 1];
|
||||
>idx : number[]
|
||||
>[...index, i + 1] : number[]
|
||||
>...index : number
|
||||
>index : number[]
|
||||
>i + 1 : number
|
||||
>i : number
|
||||
>1 : 1
|
||||
|
||||
return html('li', [
|
||||
>html('li', [ html('a', { href: `#${el.id}`, rel: 'noopener', 'data-index': idx.join('.') }, el.textContent!), children.length > 0 ? parse(children, idx) : frag() ]) : any
|
||||
>html : any
|
||||
>'li' : "li"
|
||||
>[ html('a', { href: `#${el.id}`, rel: 'noopener', 'data-index': idx.join('.') }, el.textContent!), children.length > 0 ? parse(children, idx) : frag() ] : any[]
|
||||
|
||||
html('a', { href: `#${el.id}`, rel: 'noopener', 'data-index': idx.join('.') }, el.textContent!),
|
||||
>html('a', { href: `#${el.id}`, rel: 'noopener', 'data-index': idx.join('.') }, el.textContent!) : any
|
||||
>html : any
|
||||
>'a' : "a"
|
||||
>{ href: `#${el.id}`, rel: 'noopener', 'data-index': idx.join('.') } : { href: string; rel: string; 'data-index': string; }
|
||||
>href : string
|
||||
>`#${el.id}` : string
|
||||
>el.id : string
|
||||
>el : HTMLHeadingElement
|
||||
>id : string
|
||||
>rel : string
|
||||
>'noopener' : "noopener"
|
||||
>'data-index' : string
|
||||
>idx.join('.') : string
|
||||
>idx.join : (separator?: string | undefined) => string
|
||||
>idx : number[]
|
||||
>join : (separator?: string | undefined) => string
|
||||
>'.' : "."
|
||||
>el.textContent! : string
|
||||
>el.textContent : string | null
|
||||
>el : HTMLHeadingElement
|
||||
>textContent : string | null
|
||||
|
||||
children.length > 0 ? parse(children, idx) : frag()
|
||||
>children.length > 0 ? parse(children, idx) : frag() : any
|
||||
>children.length > 0 : boolean
|
||||
>children.length : number
|
||||
>children : Tree
|
||||
>length : number
|
||||
>0 : 0
|
||||
>parse(children, idx) : HTMLUListElement
|
||||
>parse : (node: Tree, index?: number[]) => HTMLUListElement
|
||||
>children : Tree
|
||||
>idx : number[]
|
||||
>frag() : any
|
||||
>frag : any
|
||||
|
||||
]);
|
||||
}));
|
||||
}
|
||||
|
||||
function cons(hs: HTMLHeadingElement[]): Tree {
|
||||
>cons : (hs: HTMLHeadingElement[]) => Tree
|
||||
>hs : HTMLHeadingElement[]
|
||||
|
||||
return hs
|
||||
>hs .reduce<HTMLHeadingElement[][]>((hss, h) => { const hs = hss.pop()!; return hs.length === 0 || level(h) > level(hs[0]) ? concat(hss, [concat(hs, [h])]) : concat(hss, [hs, [h]]); }, [[]]) .reduce<Tree>((node, hs) => hs.length === 0 ? node : concat<Tree[number]>(node, [[hs.shift()!, cons(hs)]]) , []) : Tree
|
||||
>hs .reduce<HTMLHeadingElement[][]>((hss, h) => { const hs = hss.pop()!; return hs.length === 0 || level(h) > level(hs[0]) ? concat(hss, [concat(hs, [h])]) : concat(hss, [hs, [h]]); }, [[]]) .reduce : { (callbackfn: (previousValue: HTMLHeadingElement[], currentValue: HTMLHeadingElement[], currentIndex: number, array: HTMLHeadingElement[][]) => HTMLHeadingElement[]): HTMLHeadingElement[]; (callbackfn: (previousValue: HTMLHeadingElement[], currentValue: HTMLHeadingElement[], currentIndex: number, array: HTMLHeadingElement[][]) => HTMLHeadingElement[], initialValue: HTMLHeadingElement[]): HTMLHeadingElement[]; <U>(callbackfn: (previousValue: U, currentValue: HTMLHeadingElement[], currentIndex: number, array: HTMLHeadingElement[][]) => U, initialValue: U): U; }
|
||||
>hs .reduce<HTMLHeadingElement[][]>((hss, h) => { const hs = hss.pop()!; return hs.length === 0 || level(h) > level(hs[0]) ? concat(hss, [concat(hs, [h])]) : concat(hss, [hs, [h]]); }, [[]]) : HTMLHeadingElement[][]
|
||||
>hs .reduce : { (callbackfn: (previousValue: HTMLHeadingElement, currentValue: HTMLHeadingElement, currentIndex: number, array: HTMLHeadingElement[]) => HTMLHeadingElement): HTMLHeadingElement; (callbackfn: (previousValue: HTMLHeadingElement, currentValue: HTMLHeadingElement, currentIndex: number, array: HTMLHeadingElement[]) => HTMLHeadingElement, initialValue: HTMLHeadingElement): HTMLHeadingElement; <U>(callbackfn: (previousValue: U, currentValue: HTMLHeadingElement, currentIndex: number, array: HTMLHeadingElement[]) => U, initialValue: U): U; }
|
||||
>hs : HTMLHeadingElement[]
|
||||
|
||||
.reduce<HTMLHeadingElement[][]>((hss, h) => {
|
||||
>reduce : { (callbackfn: (previousValue: HTMLHeadingElement, currentValue: HTMLHeadingElement, currentIndex: number, array: HTMLHeadingElement[]) => HTMLHeadingElement): HTMLHeadingElement; (callbackfn: (previousValue: HTMLHeadingElement, currentValue: HTMLHeadingElement, currentIndex: number, array: HTMLHeadingElement[]) => HTMLHeadingElement, initialValue: HTMLHeadingElement): HTMLHeadingElement; <U>(callbackfn: (previousValue: U, currentValue: HTMLHeadingElement, currentIndex: number, array: HTMLHeadingElement[]) => U, initialValue: U): U; }
|
||||
>(hss, h) => { const hs = hss.pop()!; return hs.length === 0 || level(h) > level(hs[0]) ? concat(hss, [concat(hs, [h])]) : concat(hss, [hs, [h]]); } : (hss: HTMLHeadingElement[][], h: HTMLHeadingElement) => any
|
||||
>hss : HTMLHeadingElement[][]
|
||||
>h : HTMLHeadingElement
|
||||
|
||||
const hs = hss.pop()!;
|
||||
>hs : HTMLHeadingElement[]
|
||||
>hss.pop()! : HTMLHeadingElement[]
|
||||
>hss.pop() : HTMLHeadingElement[] | undefined
|
||||
>hss.pop : () => HTMLHeadingElement[] | undefined
|
||||
>hss : HTMLHeadingElement[][]
|
||||
>pop : () => HTMLHeadingElement[] | undefined
|
||||
|
||||
return hs.length === 0 || level(h) > level(hs[0])
|
||||
>hs.length === 0 || level(h) > level(hs[0]) ? concat(hss, [concat(hs, [h])]) : concat(hss, [hs, [h]]) : any
|
||||
>hs.length === 0 || level(h) > level(hs[0]) : boolean
|
||||
>hs.length === 0 : boolean
|
||||
>hs.length : number
|
||||
>hs : HTMLHeadingElement[]
|
||||
>length : number
|
||||
>0 : 0
|
||||
>level(h) > level(hs[0]) : boolean
|
||||
>level(h) : number
|
||||
>level : (h: HTMLHeadingElement) => number
|
||||
>h : HTMLHeadingElement
|
||||
>level(hs[0]) : number
|
||||
>level : (h: HTMLHeadingElement) => number
|
||||
>hs[0] : HTMLHeadingElement
|
||||
>hs : HTMLHeadingElement[]
|
||||
>0 : 0
|
||||
|
||||
? concat(hss, [concat(hs, [h])])
|
||||
>concat(hss, [concat(hs, [h])]) : any
|
||||
>concat : any
|
||||
>hss : HTMLHeadingElement[][]
|
||||
>[concat(hs, [h])] : any[]
|
||||
>concat(hs, [h]) : any
|
||||
>concat : any
|
||||
>hs : HTMLHeadingElement[]
|
||||
>[h] : HTMLHeadingElement[]
|
||||
>h : HTMLHeadingElement
|
||||
|
||||
: concat(hss, [hs, [h]]);
|
||||
>concat(hss, [hs, [h]]) : any
|
||||
>concat : any
|
||||
>hss : HTMLHeadingElement[][]
|
||||
>[hs, [h]] : HTMLHeadingElement[][]
|
||||
>hs : HTMLHeadingElement[]
|
||||
>[h] : HTMLHeadingElement[]
|
||||
>h : HTMLHeadingElement
|
||||
|
||||
}, [[]])
|
||||
>[[]] : never[][]
|
||||
>[] : never[]
|
||||
|
||||
.reduce<Tree>((node, hs) =>
|
||||
>reduce : { (callbackfn: (previousValue: HTMLHeadingElement[], currentValue: HTMLHeadingElement[], currentIndex: number, array: HTMLHeadingElement[][]) => HTMLHeadingElement[]): HTMLHeadingElement[]; (callbackfn: (previousValue: HTMLHeadingElement[], currentValue: HTMLHeadingElement[], currentIndex: number, array: HTMLHeadingElement[][]) => HTMLHeadingElement[], initialValue: HTMLHeadingElement[]): HTMLHeadingElement[]; <U>(callbackfn: (previousValue: U, currentValue: HTMLHeadingElement[], currentIndex: number, array: HTMLHeadingElement[][]) => U, initialValue: U): U; }
|
||||
>(node, hs) => hs.length === 0 ? node : concat<Tree[number]>(node, [[hs.shift()!, cons(hs)]]) : (node: Tree, hs: HTMLHeadingElement[]) => any
|
||||
>node : Tree
|
||||
>hs : HTMLHeadingElement[]
|
||||
|
||||
hs.length === 0
|
||||
>hs.length === 0 ? node : concat<Tree[number]>(node, [[hs.shift()!, cons(hs)]]) : any
|
||||
>hs.length === 0 : boolean
|
||||
>hs.length : number
|
||||
>hs : HTMLHeadingElement[]
|
||||
>length : number
|
||||
>0 : 0
|
||||
|
||||
? node
|
||||
>node : Tree
|
||||
|
||||
: concat<Tree[number]>(node, [[hs.shift()!, cons(hs)]])
|
||||
>concat<Tree[number]>(node, [[hs.shift()!, cons(hs)]]) : any
|
||||
>concat : any
|
||||
>node : Tree
|
||||
>[[hs.shift()!, cons(hs)]] : (HTMLHeadingElement | Tree)[][]
|
||||
>[hs.shift()!, cons(hs)] : (HTMLHeadingElement | Tree)[]
|
||||
>hs.shift()! : HTMLHeadingElement
|
||||
>hs.shift() : HTMLHeadingElement | undefined
|
||||
>hs.shift : () => HTMLHeadingElement | undefined
|
||||
>hs : HTMLHeadingElement[]
|
||||
>shift : () => HTMLHeadingElement | undefined
|
||||
>cons(hs) : Tree
|
||||
>cons : (hs: HTMLHeadingElement[]) => Tree
|
||||
>hs : HTMLHeadingElement[]
|
||||
|
||||
, []);
|
||||
>[] : never[]
|
||||
}
|
||||
|
||||
function level(h: HTMLHeadingElement): number {
|
||||
>level : (h: HTMLHeadingElement) => number
|
||||
>h : HTMLHeadingElement
|
||||
|
||||
assert(isFinite(+h.tagName[1]));
|
||||
>assert(isFinite(+h.tagName[1])) : any
|
||||
>assert : any
|
||||
>isFinite(+h.tagName[1]) : boolean
|
||||
>isFinite : (number: number) => boolean
|
||||
>+h.tagName[1] : number
|
||||
>h.tagName[1] : string
|
||||
>h.tagName : string
|
||||
>h : HTMLHeadingElement
|
||||
>tagName : string
|
||||
>1 : 1
|
||||
|
||||
return +h.tagName[1];
|
||||
>+h.tagName[1] : number
|
||||
>h.tagName[1] : string
|
||||
>h.tagName : string
|
||||
>h : HTMLHeadingElement
|
||||
>tagName : string
|
||||
>1 : 1
|
||||
}
|
||||
|
||||
|
|
|
@ -80,3 +80,53 @@ type T12 = (T12)[];
|
|||
type T13 = T13[] | string;
|
||||
type T14 = T14[] & { x: string };
|
||||
type T15<X> = X extends string ? T15<X>[] : never;
|
||||
|
||||
type ValueOrArray1<T> = T | ValueOrArray1<T>[];
|
||||
type ValueOrArray2<T> = T | ValueOrArray2<T>[];
|
||||
|
||||
declare function foo1<T>(a: ValueOrArray1<T>): T;
|
||||
declare let ra1: ValueOrArray2<string>;
|
||||
|
||||
let x1 = foo1(ra1); // Boom!
|
||||
|
||||
type NumberOrArray1<T> = T | ValueOrArray1<T>[];
|
||||
type NumberOrArray2<T> = T | ValueOrArray2<T>[];
|
||||
|
||||
declare function foo2<T>(a: ValueOrArray1<T>): T;
|
||||
declare let ra2: ValueOrArray2<string>;
|
||||
|
||||
let x2 = foo2(ra2); // Boom!
|
||||
|
||||
// Repro from #33617 (errors are expected)
|
||||
|
||||
type Tree = [HTMLHeadingElement, Tree][];
|
||||
|
||||
function parse(node: Tree, index: number[] = []): HTMLUListElement {
|
||||
return html('ul', node.map(([el, children], i) => {
|
||||
const idx = [...index, i + 1];
|
||||
return html('li', [
|
||||
html('a', { href: `#${el.id}`, rel: 'noopener', 'data-index': idx.join('.') }, el.textContent!),
|
||||
children.length > 0 ? parse(children, idx) : frag()
|
||||
]);
|
||||
}));
|
||||
}
|
||||
|
||||
function cons(hs: HTMLHeadingElement[]): Tree {
|
||||
return hs
|
||||
.reduce<HTMLHeadingElement[][]>((hss, h) => {
|
||||
const hs = hss.pop()!;
|
||||
return hs.length === 0 || level(h) > level(hs[0])
|
||||
? concat(hss, [concat(hs, [h])])
|
||||
: concat(hss, [hs, [h]]);
|
||||
}, [[]])
|
||||
.reduce<Tree>((node, hs) =>
|
||||
hs.length === 0
|
||||
? node
|
||||
: concat<Tree[number]>(node, [[hs.shift()!, cons(hs)]])
|
||||
, []);
|
||||
}
|
||||
|
||||
function level(h: HTMLHeadingElement): number {
|
||||
assert(isFinite(+h.tagName[1]));
|
||||
return +h.tagName[1];
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue