Remove special any
assignability for numeric index signatures (#41660)
* Only enable special assignability rule on string index signatures to 'any'. * Accepted baselines. * Added test. * Accepted baselines. * Renamed test files. * Add non-erroring version of bclas'subClassThisTypeAssignable01.ts' * Accepted baselines. Co-authored-by: TypeScript Bot <typescriptbot@microsoft.com>
This commit is contained in:
parent
2c5cee59f0
commit
df5ffc0ea1
|
@ -18948,7 +18948,7 @@ namespace ts {
|
|||
return indexTypesIdenticalTo(source, target, kind);
|
||||
}
|
||||
const targetType = getIndexTypeOfType(target, kind);
|
||||
if (!targetType || targetType.flags & TypeFlags.Any && !sourceIsPrimitive) {
|
||||
if (!targetType || targetType.flags & TypeFlags.Any && !sourceIsPrimitive && kind === IndexKind.String) {
|
||||
// Index signature of type any permits assignment from everything but primitives
|
||||
return Ternary.True;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
tests/cases/compiler/functionAssignabilityWithArrayLike01.ts(2,7): error TS2322: Type '() => void' is not assignable to type 'ArrayLike<any>'.
|
||||
Index signature is missing in type '() => void'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/functionAssignabilityWithArrayLike01.ts (1 errors) ====
|
||||
function func() {}
|
||||
const array: ArrayLike<any> = func;
|
||||
~~~~~
|
||||
!!! error TS2322: Type '() => void' is not assignable to type 'ArrayLike<any>'.
|
||||
!!! error TS2322: Index signature is missing in type '() => void'.
|
|
@ -0,0 +1,7 @@
|
|||
//// [functionAssignabilityWithArrayLike01.ts]
|
||||
function func() {}
|
||||
const array: ArrayLike<any> = func;
|
||||
|
||||
//// [functionAssignabilityWithArrayLike01.js]
|
||||
function func() { }
|
||||
var array = func;
|
|
@ -0,0 +1,9 @@
|
|||
=== tests/cases/compiler/functionAssignabilityWithArrayLike01.ts ===
|
||||
function func() {}
|
||||
>func : Symbol(func, Decl(functionAssignabilityWithArrayLike01.ts, 0, 0))
|
||||
|
||||
const array: ArrayLike<any> = func;
|
||||
>array : Symbol(array, Decl(functionAssignabilityWithArrayLike01.ts, 1, 5))
|
||||
>ArrayLike : Symbol(ArrayLike, Decl(lib.es5.d.ts, --, --))
|
||||
>func : Symbol(func, Decl(functionAssignabilityWithArrayLike01.ts, 0, 0))
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
=== tests/cases/compiler/functionAssignabilityWithArrayLike01.ts ===
|
||||
function func() {}
|
||||
>func : () => void
|
||||
|
||||
const array: ArrayLike<any> = func;
|
||||
>array : ArrayLike<any>
|
||||
>func : () => void
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
tests/cases/compiler/functionAssignabilityWithArrayLike01.ts(2,7): error TS2322: Type '() => void' is not assignable to type 'ArrayLike<any>'.
|
||||
Index signature is missing in type '() => void'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/functionAssignabilityWithArrayLike01.ts (1 errors) ====
|
||||
function func() {}
|
||||
const array: ArrayLike<any> = func;
|
||||
~~~~~
|
||||
!!! error TS2322: Type '() => void' is not assignable to type 'ArrayLike<any>'.
|
||||
!!! error TS2322: Index signature is missing in type '() => void'.
|
|
@ -0,0 +1,8 @@
|
|||
//// [functionAssignabilityWithArrayLike01.ts]
|
||||
function func() {}
|
||||
const array: ArrayLike<any> = func;
|
||||
|
||||
//// [functionAssignabilityWithArrayLike01.js]
|
||||
"use strict";
|
||||
function func() { }
|
||||
var array = func;
|
|
@ -0,0 +1,9 @@
|
|||
=== tests/cases/compiler/functionAssignabilityWithArrayLike01.ts ===
|
||||
function func() {}
|
||||
>func : Symbol(func, Decl(functionAssignabilityWithArrayLike01.ts, 0, 0))
|
||||
|
||||
const array: ArrayLike<any> = func;
|
||||
>array : Symbol(array, Decl(functionAssignabilityWithArrayLike01.ts, 1, 5))
|
||||
>ArrayLike : Symbol(ArrayLike, Decl(lib.es5.d.ts, --, --))
|
||||
>func : Symbol(func, Decl(functionAssignabilityWithArrayLike01.ts, 0, 0))
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
=== tests/cases/compiler/functionAssignabilityWithArrayLike01.ts ===
|
||||
function func() {}
|
||||
>func : () => void
|
||||
|
||||
const array: ArrayLike<any> = func;
|
||||
>array : ArrayLike<any>
|
||||
>func : () => void
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
tests/cases/compiler/tile1.ts(6,81): error TS2744: Type parameter defaults can only reference previously declared type parameters.
|
||||
|
||||
|
||||
==== tests/cases/compiler/tile1.ts (1 errors) ====
|
||||
interface Lifecycle<Attrs, State> {
|
||||
oninit?(vnode: Vnode<Attrs, State>): number;
|
||||
[_: number]: any;
|
||||
}
|
||||
|
||||
interface Vnode<Attrs, State extends Lifecycle<Attrs, State> = Lifecycle<Attrs, State>> {
|
||||
~~~~~
|
||||
!!! error TS2744: Type parameter defaults can only reference previously declared type parameters.
|
||||
tag: Component<Attrs, State>;
|
||||
}
|
||||
|
||||
interface Component<Attrs, State> {
|
||||
view(this: State, vnode: Vnode<Attrs, State>): number;
|
||||
}
|
||||
|
||||
interface ClassComponent<A> extends Lifecycle<A, ClassComponent<A>> {
|
||||
oninit?(vnode: Vnode<A, this>): number;
|
||||
view(vnode: Vnode<A, this>): number;
|
||||
}
|
||||
|
||||
interface MyAttrs { id: number }
|
||||
class C implements ClassComponent<MyAttrs> {
|
||||
view(v: Vnode<MyAttrs>) { return 0; }
|
||||
}
|
||||
|
||||
const test8: ClassComponent<any> = new C();
|
||||
==== tests/cases/compiler/file1.js (0 errors) ====
|
||||
/** @type {ClassComponent<any>} */
|
||||
const test9 = new C();
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
tests/cases/compiler/file1.js(2,7): error TS2322: Type 'C' is not assignable to type 'ClassComponent<any>'.
|
||||
tests/cases/compiler/tile1.ts(2,30): error TS2344: Type 'State' does not satisfy the constraint 'Lifecycle<Attrs, State>'.
|
||||
tests/cases/compiler/tile1.ts(6,81): error TS2744: Type parameter defaults can only reference previously declared type parameters.
|
||||
tests/cases/compiler/tile1.ts(11,40): error TS2344: Type 'State' does not satisfy the constraint 'Lifecycle<Attrs, State>'.
|
||||
tests/cases/compiler/tile1.ts(21,2): error TS2416: Property 'view' in type 'C' is not assignable to the same property in base type 'ClassComponent<MyAttrs>'.
|
||||
Type '(v: Vnode<MyAttrs, Lifecycle<MyAttrs, any>>) => number' is not assignable to type '(vnode: Vnode<MyAttrs, this>) => number'.
|
||||
Types of parameters 'v' and 'vnode' are incompatible.
|
||||
Type 'Vnode<MyAttrs, this>' is not assignable to type 'Vnode<MyAttrs, Lifecycle<MyAttrs, any>>'.
|
||||
Type 'this' is not assignable to type 'Lifecycle<MyAttrs, any>'.
|
||||
Type 'C' is not assignable to type 'Lifecycle<MyAttrs, any>'.
|
||||
Index signature is missing in type 'C'.
|
||||
tests/cases/compiler/tile1.ts(24,7): error TS2322: Type 'C' is not assignable to type 'ClassComponent<any>'.
|
||||
Index signature is missing in type 'C'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/tile1.ts (5 errors) ====
|
||||
interface Lifecycle<Attrs, State> {
|
||||
oninit?(vnode: Vnode<Attrs, State>): number;
|
||||
~~~~~
|
||||
!!! error TS2344: Type 'State' does not satisfy the constraint 'Lifecycle<Attrs, State>'.
|
||||
[_: number]: any;
|
||||
}
|
||||
|
||||
interface Vnode<Attrs, State extends Lifecycle<Attrs, State> = Lifecycle<Attrs, State>> {
|
||||
~~~~~
|
||||
!!! error TS2744: Type parameter defaults can only reference previously declared type parameters.
|
||||
tag: Component<Attrs, State>;
|
||||
}
|
||||
|
||||
interface Component<Attrs, State> {
|
||||
view(this: State, vnode: Vnode<Attrs, State>): number;
|
||||
~~~~~
|
||||
!!! error TS2344: Type 'State' does not satisfy the constraint 'Lifecycle<Attrs, State>'.
|
||||
}
|
||||
|
||||
interface ClassComponent<A> extends Lifecycle<A, ClassComponent<A>> {
|
||||
oninit?(vnode: Vnode<A, this>): number;
|
||||
view(vnode: Vnode<A, this>): number;
|
||||
}
|
||||
|
||||
interface MyAttrs { id: number }
|
||||
class C implements ClassComponent<MyAttrs> {
|
||||
view(v: Vnode<MyAttrs>) { return 0; }
|
||||
~~~~
|
||||
!!! error TS2416: Property 'view' in type 'C' is not assignable to the same property in base type 'ClassComponent<MyAttrs>'.
|
||||
!!! error TS2416: Type '(v: Vnode<MyAttrs, Lifecycle<MyAttrs, any>>) => number' is not assignable to type '(vnode: Vnode<MyAttrs, this>) => number'.
|
||||
!!! error TS2416: Types of parameters 'v' and 'vnode' are incompatible.
|
||||
!!! error TS2416: Type 'Vnode<MyAttrs, this>' is not assignable to type 'Vnode<MyAttrs, Lifecycle<MyAttrs, any>>'.
|
||||
!!! error TS2416: Type 'this' is not assignable to type 'Lifecycle<MyAttrs, any>'.
|
||||
!!! error TS2416: Type 'C' is not assignable to type 'Lifecycle<MyAttrs, any>'.
|
||||
!!! error TS2416: Index signature is missing in type 'C'.
|
||||
}
|
||||
|
||||
const test8: ClassComponent<any> = new C();
|
||||
~~~~~
|
||||
!!! error TS2322: Type 'C' is not assignable to type 'ClassComponent<any>'.
|
||||
!!! error TS2322: Index signature is missing in type 'C'.
|
||||
==== tests/cases/compiler/file1.js (1 errors) ====
|
||||
/** @type {ClassComponent<any>} */
|
||||
const test9 = new C();
|
||||
~~~~~
|
||||
!!! error TS2322: Type 'C' is not assignable to type 'ClassComponent<any>'.
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
//// [tests/cases/compiler/subclassThisTypeAssignable.ts] ////
|
||||
//// [tests/cases/compiler/subclassThisTypeAssignable01.ts] ////
|
||||
|
||||
//// [tile1.ts]
|
||||
interface Lifecycle<Attrs, State> {
|
49
tests/baselines/reference/subclassThisTypeAssignable02.js
Normal file
49
tests/baselines/reference/subclassThisTypeAssignable02.js
Normal file
|
@ -0,0 +1,49 @@
|
|||
//// [tests/cases/compiler/subclassThisTypeAssignable02.ts] ////
|
||||
|
||||
//// [tile1.ts]
|
||||
interface Lifecycle<Attrs, State extends Lifecycle<Attrs, State>> {
|
||||
oninit?(vnode: Vnode<Attrs, State>): number;
|
||||
[_: number]: any;
|
||||
}
|
||||
|
||||
interface Vnode<Attrs, State extends Lifecycle<Attrs, State>> {
|
||||
tag: Component<Attrs, State>;
|
||||
}
|
||||
|
||||
interface Component<Attrs, State extends Lifecycle<Attrs, State>> {
|
||||
view(this: State, vnode: Vnode<Attrs, State>): number;
|
||||
}
|
||||
|
||||
interface ClassComponent<A> extends Lifecycle<A, ClassComponent<A>> {
|
||||
oninit?(vnode: Vnode<A, this>): number;
|
||||
view(vnode: Vnode<A, this>): number;
|
||||
}
|
||||
|
||||
interface MyAttrs { id: number }
|
||||
class C implements ClassComponent<MyAttrs> {
|
||||
view(v: Vnode<MyAttrs, C>) { return 0; }
|
||||
|
||||
// Must declare a compatible-ish index signature or else
|
||||
// we won't correctly implement ClassComponent.
|
||||
[_: number]: unknown;
|
||||
}
|
||||
|
||||
const test8: ClassComponent<any> = new C();
|
||||
//// [file1.js]
|
||||
/** @type {ClassComponent<any>} */
|
||||
const test9 = new C();
|
||||
|
||||
|
||||
//// [tile1.js]
|
||||
"use strict";
|
||||
var C = /** @class */ (function () {
|
||||
function C() {
|
||||
}
|
||||
C.prototype.view = function (v) { return 0; };
|
||||
return C;
|
||||
}());
|
||||
var test8 = new C();
|
||||
//// [file1.js]
|
||||
"use strict";
|
||||
/** @type {ClassComponent<any>} */
|
||||
var test9 = new C();
|
107
tests/baselines/reference/subclassThisTypeAssignable02.symbols
Normal file
107
tests/baselines/reference/subclassThisTypeAssignable02.symbols
Normal file
|
@ -0,0 +1,107 @@
|
|||
=== tests/cases/compiler/tile1.ts ===
|
||||
interface Lifecycle<Attrs, State extends Lifecycle<Attrs, State>> {
|
||||
>Lifecycle : Symbol(Lifecycle, Decl(tile1.ts, 0, 0))
|
||||
>Attrs : Symbol(Attrs, Decl(tile1.ts, 0, 20))
|
||||
>State : Symbol(State, Decl(tile1.ts, 0, 26))
|
||||
>Lifecycle : Symbol(Lifecycle, Decl(tile1.ts, 0, 0))
|
||||
>Attrs : Symbol(Attrs, Decl(tile1.ts, 0, 20))
|
||||
>State : Symbol(State, Decl(tile1.ts, 0, 26))
|
||||
|
||||
oninit?(vnode: Vnode<Attrs, State>): number;
|
||||
>oninit : Symbol(Lifecycle.oninit, Decl(tile1.ts, 0, 67))
|
||||
>vnode : Symbol(vnode, Decl(tile1.ts, 1, 9))
|
||||
>Vnode : Symbol(Vnode, Decl(tile1.ts, 3, 1))
|
||||
>Attrs : Symbol(Attrs, Decl(tile1.ts, 0, 20))
|
||||
>State : Symbol(State, Decl(tile1.ts, 0, 26))
|
||||
|
||||
[_: number]: any;
|
||||
>_ : Symbol(_, Decl(tile1.ts, 2, 2))
|
||||
}
|
||||
|
||||
interface Vnode<Attrs, State extends Lifecycle<Attrs, State>> {
|
||||
>Vnode : Symbol(Vnode, Decl(tile1.ts, 3, 1))
|
||||
>Attrs : Symbol(Attrs, Decl(tile1.ts, 5, 16))
|
||||
>State : Symbol(State, Decl(tile1.ts, 5, 22))
|
||||
>Lifecycle : Symbol(Lifecycle, Decl(tile1.ts, 0, 0))
|
||||
>Attrs : Symbol(Attrs, Decl(tile1.ts, 5, 16))
|
||||
>State : Symbol(State, Decl(tile1.ts, 5, 22))
|
||||
|
||||
tag: Component<Attrs, State>;
|
||||
>tag : Symbol(Vnode.tag, Decl(tile1.ts, 5, 63))
|
||||
>Component : Symbol(Component, Decl(tile1.ts, 7, 1))
|
||||
>Attrs : Symbol(Attrs, Decl(tile1.ts, 5, 16))
|
||||
>State : Symbol(State, Decl(tile1.ts, 5, 22))
|
||||
}
|
||||
|
||||
interface Component<Attrs, State extends Lifecycle<Attrs, State>> {
|
||||
>Component : Symbol(Component, Decl(tile1.ts, 7, 1))
|
||||
>Attrs : Symbol(Attrs, Decl(tile1.ts, 9, 20))
|
||||
>State : Symbol(State, Decl(tile1.ts, 9, 26))
|
||||
>Lifecycle : Symbol(Lifecycle, Decl(tile1.ts, 0, 0))
|
||||
>Attrs : Symbol(Attrs, Decl(tile1.ts, 9, 20))
|
||||
>State : Symbol(State, Decl(tile1.ts, 9, 26))
|
||||
|
||||
view(this: State, vnode: Vnode<Attrs, State>): number;
|
||||
>view : Symbol(Component.view, Decl(tile1.ts, 9, 67))
|
||||
>this : Symbol(this, Decl(tile1.ts, 10, 6))
|
||||
>State : Symbol(State, Decl(tile1.ts, 9, 26))
|
||||
>vnode : Symbol(vnode, Decl(tile1.ts, 10, 18))
|
||||
>Vnode : Symbol(Vnode, Decl(tile1.ts, 3, 1))
|
||||
>Attrs : Symbol(Attrs, Decl(tile1.ts, 9, 20))
|
||||
>State : Symbol(State, Decl(tile1.ts, 9, 26))
|
||||
}
|
||||
|
||||
interface ClassComponent<A> extends Lifecycle<A, ClassComponent<A>> {
|
||||
>ClassComponent : Symbol(ClassComponent, Decl(tile1.ts, 11, 1))
|
||||
>A : Symbol(A, Decl(tile1.ts, 13, 25))
|
||||
>Lifecycle : Symbol(Lifecycle, Decl(tile1.ts, 0, 0))
|
||||
>A : Symbol(A, Decl(tile1.ts, 13, 25))
|
||||
>ClassComponent : Symbol(ClassComponent, Decl(tile1.ts, 11, 1))
|
||||
>A : Symbol(A, Decl(tile1.ts, 13, 25))
|
||||
|
||||
oninit?(vnode: Vnode<A, this>): number;
|
||||
>oninit : Symbol(ClassComponent.oninit, Decl(tile1.ts, 13, 69))
|
||||
>vnode : Symbol(vnode, Decl(tile1.ts, 14, 9))
|
||||
>Vnode : Symbol(Vnode, Decl(tile1.ts, 3, 1))
|
||||
>A : Symbol(A, Decl(tile1.ts, 13, 25))
|
||||
|
||||
view(vnode: Vnode<A, this>): number;
|
||||
>view : Symbol(ClassComponent.view, Decl(tile1.ts, 14, 40))
|
||||
>vnode : Symbol(vnode, Decl(tile1.ts, 15, 6))
|
||||
>Vnode : Symbol(Vnode, Decl(tile1.ts, 3, 1))
|
||||
>A : Symbol(A, Decl(tile1.ts, 13, 25))
|
||||
}
|
||||
|
||||
interface MyAttrs { id: number }
|
||||
>MyAttrs : Symbol(MyAttrs, Decl(tile1.ts, 16, 1))
|
||||
>id : Symbol(MyAttrs.id, Decl(tile1.ts, 18, 19))
|
||||
|
||||
class C implements ClassComponent<MyAttrs> {
|
||||
>C : Symbol(C, Decl(tile1.ts, 18, 32))
|
||||
>ClassComponent : Symbol(ClassComponent, Decl(tile1.ts, 11, 1))
|
||||
>MyAttrs : Symbol(MyAttrs, Decl(tile1.ts, 16, 1))
|
||||
|
||||
view(v: Vnode<MyAttrs, C>) { return 0; }
|
||||
>view : Symbol(C.view, Decl(tile1.ts, 19, 44))
|
||||
>v : Symbol(v, Decl(tile1.ts, 20, 6))
|
||||
>Vnode : Symbol(Vnode, Decl(tile1.ts, 3, 1))
|
||||
>MyAttrs : Symbol(MyAttrs, Decl(tile1.ts, 16, 1))
|
||||
>C : Symbol(C, Decl(tile1.ts, 18, 32))
|
||||
|
||||
// Must declare a compatible-ish index signature or else
|
||||
// we won't correctly implement ClassComponent.
|
||||
[_: number]: unknown;
|
||||
>_ : Symbol(_, Decl(tile1.ts, 24, 2))
|
||||
}
|
||||
|
||||
const test8: ClassComponent<any> = new C();
|
||||
>test8 : Symbol(test8, Decl(tile1.ts, 27, 5))
|
||||
>ClassComponent : Symbol(ClassComponent, Decl(tile1.ts, 11, 1))
|
||||
>C : Symbol(C, Decl(tile1.ts, 18, 32))
|
||||
|
||||
=== tests/cases/compiler/file1.js ===
|
||||
/** @type {ClassComponent<any>} */
|
||||
const test9 = new C();
|
||||
>test9 : Symbol(test9, Decl(file1.js, 1, 5))
|
||||
>C : Symbol(C, Decl(tile1.ts, 18, 32))
|
||||
|
61
tests/baselines/reference/subclassThisTypeAssignable02.types
Normal file
61
tests/baselines/reference/subclassThisTypeAssignable02.types
Normal file
|
@ -0,0 +1,61 @@
|
|||
=== tests/cases/compiler/tile1.ts ===
|
||||
interface Lifecycle<Attrs, State extends Lifecycle<Attrs, State>> {
|
||||
oninit?(vnode: Vnode<Attrs, State>): number;
|
||||
>oninit : ((vnode: Vnode<Attrs, State>) => number) | undefined
|
||||
>vnode : Vnode<Attrs, State>
|
||||
|
||||
[_: number]: any;
|
||||
>_ : number
|
||||
}
|
||||
|
||||
interface Vnode<Attrs, State extends Lifecycle<Attrs, State>> {
|
||||
tag: Component<Attrs, State>;
|
||||
>tag : Component<Attrs, State>
|
||||
}
|
||||
|
||||
interface Component<Attrs, State extends Lifecycle<Attrs, State>> {
|
||||
view(this: State, vnode: Vnode<Attrs, State>): number;
|
||||
>view : (this: State, vnode: Vnode<Attrs, State>) => number
|
||||
>this : State
|
||||
>vnode : Vnode<Attrs, State>
|
||||
}
|
||||
|
||||
interface ClassComponent<A> extends Lifecycle<A, ClassComponent<A>> {
|
||||
oninit?(vnode: Vnode<A, this>): number;
|
||||
>oninit : ((vnode: Vnode<A, this>) => number) | undefined
|
||||
>vnode : Vnode<A, this>
|
||||
|
||||
view(vnode: Vnode<A, this>): number;
|
||||
>view : (vnode: Vnode<A, this>) => number
|
||||
>vnode : Vnode<A, this>
|
||||
}
|
||||
|
||||
interface MyAttrs { id: number }
|
||||
>id : number
|
||||
|
||||
class C implements ClassComponent<MyAttrs> {
|
||||
>C : C
|
||||
|
||||
view(v: Vnode<MyAttrs, C>) { return 0; }
|
||||
>view : (v: Vnode<MyAttrs, C>) => number
|
||||
>v : Vnode<MyAttrs, C>
|
||||
>0 : 0
|
||||
|
||||
// Must declare a compatible-ish index signature or else
|
||||
// we won't correctly implement ClassComponent.
|
||||
[_: number]: unknown;
|
||||
>_ : number
|
||||
}
|
||||
|
||||
const test8: ClassComponent<any> = new C();
|
||||
>test8 : ClassComponent<any>
|
||||
>new C() : C
|
||||
>C : typeof C
|
||||
|
||||
=== tests/cases/compiler/file1.js ===
|
||||
/** @type {ClassComponent<any>} */
|
||||
const test9 = new C();
|
||||
>test9 : ClassComponent<any>
|
||||
>new C() : C
|
||||
>C : typeof C
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
// @strict: true, false
|
||||
|
||||
function func() {}
|
||||
const array: ArrayLike<any> = func;
|
37
tests/cases/compiler/subclassThisTypeAssignable02.ts
Normal file
37
tests/cases/compiler/subclassThisTypeAssignable02.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @strict: true
|
||||
// @outDir: ./out
|
||||
|
||||
// @filename: tile1.ts
|
||||
interface Lifecycle<Attrs, State extends Lifecycle<Attrs, State>> {
|
||||
oninit?(vnode: Vnode<Attrs, State>): number;
|
||||
[_: number]: any;
|
||||
}
|
||||
|
||||
interface Vnode<Attrs, State extends Lifecycle<Attrs, State>> {
|
||||
tag: Component<Attrs, State>;
|
||||
}
|
||||
|
||||
interface Component<Attrs, State extends Lifecycle<Attrs, State>> {
|
||||
view(this: State, vnode: Vnode<Attrs, State>): number;
|
||||
}
|
||||
|
||||
interface ClassComponent<A> extends Lifecycle<A, ClassComponent<A>> {
|
||||
oninit?(vnode: Vnode<A, this>): number;
|
||||
view(vnode: Vnode<A, this>): number;
|
||||
}
|
||||
|
||||
interface MyAttrs { id: number }
|
||||
class C implements ClassComponent<MyAttrs> {
|
||||
view(v: Vnode<MyAttrs, C>) { return 0; }
|
||||
|
||||
// Must declare a compatible-ish index signature or else
|
||||
// we won't correctly implement ClassComponent.
|
||||
[_: number]: unknown;
|
||||
}
|
||||
|
||||
const test8: ClassComponent<any> = new C();
|
||||
// @filename: file1.js
|
||||
/** @type {ClassComponent<any>} */
|
||||
const test9 = new C();
|
Loading…
Reference in a new issue