diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9d089eb7299b0..326c2bea3eafe 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18882,7 +18882,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; } diff --git a/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=false).errors.txt b/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=false).errors.txt new file mode 100644 index 0000000000000..c37fde9ead1e6 --- /dev/null +++ b/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=false).errors.txt @@ -0,0 +1,10 @@ +tests/cases/compiler/functionAssignabilityWithArrayLike01.ts(2,7): error TS2322: Type '() => void' is not assignable to type 'ArrayLike'. + Index signature is missing in type '() => void'. + + +==== tests/cases/compiler/functionAssignabilityWithArrayLike01.ts (1 errors) ==== + function func() {} + const array: ArrayLike = func; + ~~~~~ +!!! error TS2322: Type '() => void' is not assignable to type 'ArrayLike'. +!!! error TS2322: Index signature is missing in type '() => void'. \ No newline at end of file diff --git a/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=false).js b/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=false).js new file mode 100644 index 0000000000000..405bcf28ddfa0 --- /dev/null +++ b/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=false).js @@ -0,0 +1,7 @@ +//// [functionAssignabilityWithArrayLike01.ts] +function func() {} +const array: ArrayLike = func; + +//// [functionAssignabilityWithArrayLike01.js] +function func() { } +var array = func; diff --git a/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=false).symbols b/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=false).symbols new file mode 100644 index 0000000000000..20e95d52f53b3 --- /dev/null +++ b/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=false).symbols @@ -0,0 +1,9 @@ +=== tests/cases/compiler/functionAssignabilityWithArrayLike01.ts === +function func() {} +>func : Symbol(func, Decl(functionAssignabilityWithArrayLike01.ts, 0, 0)) + +const array: ArrayLike = 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)) + diff --git a/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=false).types b/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=false).types new file mode 100644 index 0000000000000..dea6f06f3a94e --- /dev/null +++ b/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=false).types @@ -0,0 +1,8 @@ +=== tests/cases/compiler/functionAssignabilityWithArrayLike01.ts === +function func() {} +>func : () => void + +const array: ArrayLike = func; +>array : ArrayLike +>func : () => void + diff --git a/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=true).errors.txt b/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=true).errors.txt new file mode 100644 index 0000000000000..c37fde9ead1e6 --- /dev/null +++ b/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=true).errors.txt @@ -0,0 +1,10 @@ +tests/cases/compiler/functionAssignabilityWithArrayLike01.ts(2,7): error TS2322: Type '() => void' is not assignable to type 'ArrayLike'. + Index signature is missing in type '() => void'. + + +==== tests/cases/compiler/functionAssignabilityWithArrayLike01.ts (1 errors) ==== + function func() {} + const array: ArrayLike = func; + ~~~~~ +!!! error TS2322: Type '() => void' is not assignable to type 'ArrayLike'. +!!! error TS2322: Index signature is missing in type '() => void'. \ No newline at end of file diff --git a/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=true).js b/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=true).js new file mode 100644 index 0000000000000..a6f9f03283934 --- /dev/null +++ b/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=true).js @@ -0,0 +1,8 @@ +//// [functionAssignabilityWithArrayLike01.ts] +function func() {} +const array: ArrayLike = func; + +//// [functionAssignabilityWithArrayLike01.js] +"use strict"; +function func() { } +var array = func; diff --git a/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=true).symbols b/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=true).symbols new file mode 100644 index 0000000000000..20e95d52f53b3 --- /dev/null +++ b/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=true).symbols @@ -0,0 +1,9 @@ +=== tests/cases/compiler/functionAssignabilityWithArrayLike01.ts === +function func() {} +>func : Symbol(func, Decl(functionAssignabilityWithArrayLike01.ts, 0, 0)) + +const array: ArrayLike = 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)) + diff --git a/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=true).types b/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=true).types new file mode 100644 index 0000000000000..dea6f06f3a94e --- /dev/null +++ b/tests/baselines/reference/functionAssignabilityWithArrayLike01(strict=true).types @@ -0,0 +1,8 @@ +=== tests/cases/compiler/functionAssignabilityWithArrayLike01.ts === +function func() {} +>func : () => void + +const array: ArrayLike = func; +>array : ArrayLike +>func : () => void + diff --git a/tests/baselines/reference/subclassThisTypeAssignable.errors.txt b/tests/baselines/reference/subclassThisTypeAssignable.errors.txt deleted file mode 100644 index f1d661695d1e3..0000000000000 --- a/tests/baselines/reference/subclassThisTypeAssignable.errors.txt +++ /dev/null @@ -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 { - oninit?(vnode: Vnode): number; - [_: number]: any; - } - - interface Vnode = Lifecycle> { - ~~~~~ -!!! error TS2744: Type parameter defaults can only reference previously declared type parameters. - tag: Component; - } - - interface Component { - view(this: State, vnode: Vnode): number; - } - - interface ClassComponent extends Lifecycle> { - oninit?(vnode: Vnode): number; - view(vnode: Vnode): number; - } - - interface MyAttrs { id: number } - class C implements ClassComponent { - view(v: Vnode) { return 0; } - } - - const test8: ClassComponent = new C(); -==== tests/cases/compiler/file1.js (0 errors) ==== - /** @type {ClassComponent} */ - const test9 = new C(); - \ No newline at end of file diff --git a/tests/baselines/reference/subclassThisTypeAssignable01.errors.txt b/tests/baselines/reference/subclassThisTypeAssignable01.errors.txt new file mode 100644 index 0000000000000..d8bce35304add --- /dev/null +++ b/tests/baselines/reference/subclassThisTypeAssignable01.errors.txt @@ -0,0 +1,63 @@ +tests/cases/compiler/file1.js(2,7): error TS2322: Type 'C' is not assignable to type 'ClassComponent'. +tests/cases/compiler/tile1.ts(2,30): error TS2344: Type 'State' does not satisfy the constraint 'Lifecycle'. +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'. +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'. + Type '(v: Vnode>) => number' is not assignable to type '(vnode: Vnode) => number'. + Types of parameters 'v' and 'vnode' are incompatible. + Type 'Vnode' is not assignable to type 'Vnode>'. + Type 'this' is not assignable to type 'Lifecycle'. + Type 'C' is not assignable to type 'Lifecycle'. + Index signature is missing in type 'C'. +tests/cases/compiler/tile1.ts(24,7): error TS2322: Type 'C' is not assignable to type 'ClassComponent'. + Index signature is missing in type 'C'. + + +==== tests/cases/compiler/tile1.ts (5 errors) ==== + interface Lifecycle { + oninit?(vnode: Vnode): number; + ~~~~~ +!!! error TS2344: Type 'State' does not satisfy the constraint 'Lifecycle'. + [_: number]: any; + } + + interface Vnode = Lifecycle> { + ~~~~~ +!!! error TS2744: Type parameter defaults can only reference previously declared type parameters. + tag: Component; + } + + interface Component { + view(this: State, vnode: Vnode): number; + ~~~~~ +!!! error TS2344: Type 'State' does not satisfy the constraint 'Lifecycle'. + } + + interface ClassComponent extends Lifecycle> { + oninit?(vnode: Vnode): number; + view(vnode: Vnode): number; + } + + interface MyAttrs { id: number } + class C implements ClassComponent { + view(v: Vnode) { return 0; } + ~~~~ +!!! error TS2416: Property 'view' in type 'C' is not assignable to the same property in base type 'ClassComponent'. +!!! error TS2416: Type '(v: Vnode>) => number' is not assignable to type '(vnode: Vnode) => number'. +!!! error TS2416: Types of parameters 'v' and 'vnode' are incompatible. +!!! error TS2416: Type 'Vnode' is not assignable to type 'Vnode>'. +!!! error TS2416: Type 'this' is not assignable to type 'Lifecycle'. +!!! error TS2416: Type 'C' is not assignable to type 'Lifecycle'. +!!! error TS2416: Index signature is missing in type 'C'. + } + + const test8: ClassComponent = new C(); + ~~~~~ +!!! error TS2322: Type 'C' is not assignable to type 'ClassComponent'. +!!! error TS2322: Index signature is missing in type 'C'. +==== tests/cases/compiler/file1.js (1 errors) ==== + /** @type {ClassComponent} */ + const test9 = new C(); + ~~~~~ +!!! error TS2322: Type 'C' is not assignable to type 'ClassComponent'. + \ No newline at end of file diff --git a/tests/baselines/reference/subclassThisTypeAssignable.js b/tests/baselines/reference/subclassThisTypeAssignable01.js similarity index 92% rename from tests/baselines/reference/subclassThisTypeAssignable.js rename to tests/baselines/reference/subclassThisTypeAssignable01.js index b82e4462a0514..fbbb3bc7b7cd4 100644 --- a/tests/baselines/reference/subclassThisTypeAssignable.js +++ b/tests/baselines/reference/subclassThisTypeAssignable01.js @@ -1,4 +1,4 @@ -//// [tests/cases/compiler/subclassThisTypeAssignable.ts] //// +//// [tests/cases/compiler/subclassThisTypeAssignable01.ts] //// //// [tile1.ts] interface Lifecycle { diff --git a/tests/baselines/reference/subclassThisTypeAssignable.symbols b/tests/baselines/reference/subclassThisTypeAssignable01.symbols similarity index 100% rename from tests/baselines/reference/subclassThisTypeAssignable.symbols rename to tests/baselines/reference/subclassThisTypeAssignable01.symbols diff --git a/tests/baselines/reference/subclassThisTypeAssignable.types b/tests/baselines/reference/subclassThisTypeAssignable01.types similarity index 100% rename from tests/baselines/reference/subclassThisTypeAssignable.types rename to tests/baselines/reference/subclassThisTypeAssignable01.types diff --git a/tests/baselines/reference/subclassThisTypeAssignable02.js b/tests/baselines/reference/subclassThisTypeAssignable02.js new file mode 100644 index 0000000000000..2b79d83fa2956 --- /dev/null +++ b/tests/baselines/reference/subclassThisTypeAssignable02.js @@ -0,0 +1,49 @@ +//// [tests/cases/compiler/subclassThisTypeAssignable02.ts] //// + +//// [tile1.ts] +interface Lifecycle> { + oninit?(vnode: Vnode): number; + [_: number]: any; +} + +interface Vnode> { + tag: Component; +} + +interface Component> { + view(this: State, vnode: Vnode): number; +} + +interface ClassComponent extends Lifecycle> { + oninit?(vnode: Vnode): number; + view(vnode: Vnode): number; +} + +interface MyAttrs { id: number } +class C implements ClassComponent { + view(v: Vnode) { return 0; } + + // Must declare a compatible-ish index signature or else + // we won't correctly implement ClassComponent. + [_: number]: unknown; +} + +const test8: ClassComponent = new C(); +//// [file1.js] +/** @type {ClassComponent} */ +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} */ +var test9 = new C(); diff --git a/tests/baselines/reference/subclassThisTypeAssignable02.symbols b/tests/baselines/reference/subclassThisTypeAssignable02.symbols new file mode 100644 index 0000000000000..41aa2a4682400 --- /dev/null +++ b/tests/baselines/reference/subclassThisTypeAssignable02.symbols @@ -0,0 +1,107 @@ +=== tests/cases/compiler/tile1.ts === +interface Lifecycle> { +>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): 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> { +>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; +>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> { +>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): 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 extends Lifecycle> { +>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): 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): 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 { +>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) { 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 = 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} */ +const test9 = new C(); +>test9 : Symbol(test9, Decl(file1.js, 1, 5)) +>C : Symbol(C, Decl(tile1.ts, 18, 32)) + diff --git a/tests/baselines/reference/subclassThisTypeAssignable02.types b/tests/baselines/reference/subclassThisTypeAssignable02.types new file mode 100644 index 0000000000000..01bb847c301cb --- /dev/null +++ b/tests/baselines/reference/subclassThisTypeAssignable02.types @@ -0,0 +1,61 @@ +=== tests/cases/compiler/tile1.ts === +interface Lifecycle> { + oninit?(vnode: Vnode): number; +>oninit : ((vnode: Vnode) => number) | undefined +>vnode : Vnode + + [_: number]: any; +>_ : number +} + +interface Vnode> { + tag: Component; +>tag : Component +} + +interface Component> { + view(this: State, vnode: Vnode): number; +>view : (this: State, vnode: Vnode) => number +>this : State +>vnode : Vnode +} + +interface ClassComponent extends Lifecycle> { + oninit?(vnode: Vnode): number; +>oninit : ((vnode: Vnode) => number) | undefined +>vnode : Vnode + + view(vnode: Vnode): number; +>view : (vnode: Vnode) => number +>vnode : Vnode +} + +interface MyAttrs { id: number } +>id : number + +class C implements ClassComponent { +>C : C + + view(v: Vnode) { return 0; } +>view : (v: Vnode) => number +>v : Vnode +>0 : 0 + + // Must declare a compatible-ish index signature or else + // we won't correctly implement ClassComponent. + [_: number]: unknown; +>_ : number +} + +const test8: ClassComponent = new C(); +>test8 : ClassComponent +>new C() : C +>C : typeof C + +=== tests/cases/compiler/file1.js === +/** @type {ClassComponent} */ +const test9 = new C(); +>test9 : ClassComponent +>new C() : C +>C : typeof C + diff --git a/tests/cases/compiler/functionAssignabilityWithArrayLike01.ts b/tests/cases/compiler/functionAssignabilityWithArrayLike01.ts new file mode 100644 index 0000000000000..5efff77d0c42b --- /dev/null +++ b/tests/cases/compiler/functionAssignabilityWithArrayLike01.ts @@ -0,0 +1,4 @@ +// @strict: true, false + +function func() {} +const array: ArrayLike = func; \ No newline at end of file diff --git a/tests/cases/compiler/subclassThisTypeAssignable.ts b/tests/cases/compiler/subclassThisTypeAssignable01.ts similarity index 100% rename from tests/cases/compiler/subclassThisTypeAssignable.ts rename to tests/cases/compiler/subclassThisTypeAssignable01.ts diff --git a/tests/cases/compiler/subclassThisTypeAssignable02.ts b/tests/cases/compiler/subclassThisTypeAssignable02.ts new file mode 100644 index 0000000000000..2040fdd2742c7 --- /dev/null +++ b/tests/cases/compiler/subclassThisTypeAssignable02.ts @@ -0,0 +1,37 @@ +// @allowJs: true +// @checkJs: true +// @strict: true +// @outDir: ./out + +// @filename: tile1.ts +interface Lifecycle> { + oninit?(vnode: Vnode): number; + [_: number]: any; +} + +interface Vnode> { + tag: Component; +} + +interface Component> { + view(this: State, vnode: Vnode): number; +} + +interface ClassComponent extends Lifecycle> { + oninit?(vnode: Vnode): number; + view(vnode: Vnode): number; +} + +interface MyAttrs { id: number } +class C implements ClassComponent { + view(v: Vnode) { return 0; } + + // Must declare a compatible-ish index signature or else + // we won't correctly implement ClassComponent. + [_: number]: unknown; +} + +const test8: ClassComponent = new C(); +// @filename: file1.js +/** @type {ClassComponent} */ +const test9 = new C();