// @strict: true
// @noEmit: true
interface I0 {
p0_0: number;
}
interface I1 extends I0 {
p1_0: number;
}
interface I2 extends I1, I0 {
p2_0: number;
}
interface I3 extends I2, I1, I0 {
p3_0: number;
}
interface I4 extends I3, I2, I1, I0 {
p4_0: number;
}
interface I5 extends I4, I3, I2, I1, I0 {
p5_0: number;
}
interface I6 extends I5, I4, I3, I2, I1, I0 {
p6_0: number;
}
interface I7 extends I6, I5, I4, I3, I2, I1, I0 {
p7_0: number;
}
interface I8 extends I7, I6, I5, I4, I3, I2, I1, I0 {
p8_0: number;
}
interface I9 extends I8, I7, I6, I5, I4, I3, I2, I1 {
p9_0: number;
}
interface I10 extends I9, I8, I7, I6, I5, I4, I3, I2 {
p10_0: number;
}
interface I11 extends I10, I9, I8, I7, I6, I5, I4, I3 {
p11_0: number;
}
interface I12 extends I11, I10, I9, I8, I7, I6, I5, I4 {
p12_0: number;
}
interface I13 extends I12, I11, I10, I9, I8, I7, I6, I5 {
p13_0: number;
}
interface I14 extends I13, I12, I11, I10, I9, I8, I7, I6 {
p14_0: number;
}
interface I15 extends I14, I13, I12, I11, I10, I9, I8, I7 {
p15_0: number;
}
interface I16 extends I15, I14, I13, I12, I11, I10, I9, I8 {
p16_0: number;
}
interface I17 extends I16, I15, I14, I13, I12, I11, I10, I9 {
p17_0: number;
}
interface I18 extends I17, I16, I15, I14, I13, I12, I11, I10 {
p18_0: number;
}
interface I19 extends I18, I17, I16, I15, I14, I13, I12, I11 {
p19_0: number;
}
interface I20 extends I19, I18, I17, I16, I15, I14, I13, I12 {
p20_0: number;
}
interface I21 extends I20, I19, I18, I17, I16, I15, I14, I13 {
p21_0: number;
}
interface I22 extends I21, I20, I19, I18, I17, I16, I15, I14 {
p22_0: number;
}
interface I23 extends I22, I21, I20, I19, I18, I17, I16, I15 {
p23_0: number;
}
interface I24 extends I23, I22, I21, I20, I19, I18, I17, I16 {
p24_0: number;
}
interface I25 extends I24, I23, I22, I21, I20, I19, I18, I17 {
p25_0: number;
}
interface I26 extends I25, I24, I23, I22, I21, I20, I19, I18 {
p26_0: number;
}
interface I27 extends I26, I25, I24, I23, I22, I21, I20, I19 {
p27_0: number;
}
interface I28 extends I27, I26, I25, I24, I23, I22, I21, I20 {
p28_0: number;
}
interface I29 extends I28, I27, I26, I25, I24, I23, I22, I21 {
p29_0: number;
}
interface I30 extends I29, I28, I27, I26, I25, I24, I23, I22 {
p30_0: number;
}
interface I31 extends I30, I29, I28, I27, I26, I25, I24, I23 {
p31_0: number;
}
declare const value: I31;
value.p0_0;
Search Terms
hasBaseType, interface inheritance performance, diamond-shaped interface inheritance, base type traversal, quadratic check time
Version & Regression Information
This reproduces on TypeScript 6.0.3 and on current
mainbefore the proposed fix.Tested current
maincommit:Code
The repro is an interface-only diamond-shaped inheritance graph. Each interface extends up to 8 previous interfaces.
Full repro
Actual behavior
Before the fix, compiling the repro above timed out after 30 seconds.
The hotspot is
hasBaseType, which recursively walksgetBaseTypes(target)and can revisit the same reachable base-type subgraphs many times during one query.Expected behavior
The checker should avoid revisiting the same base-type subgraph during a single
hasBaseTypequery.With a per-call
seenset inhasBaseType, the same repro completes quickly:Proposed fix
The fix is to keep a per-call
Set<Type>insidehasBaseTypeand skip already visited class/interface/reference/intersection nodes.I have pushed a branch with the proposed fix and regression test here:
Commit:
Additional information
The branch contains:
hasBaseTypefix;Validation run:
Result:
I can open a PR with the fix if this is considered appropriate for the JS-based TypeScript repository maintenance policy.