Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7663,16 +7663,18 @@ namespace ts {
// Map an unsatisfied type parameter with a default type.
// If a type parameter does not have a default type, or if the default type
// is a forward reference, the empty object type is used.
const baseDefaultType = getDefaultTypeArgumentType(isJavaScriptImplicitAny);
const cicrularityMapper = createTypeMapper(typeParameters!, map(typeParameters!, () => baseDefaultType));
Comment thread
weswigham marked this conversation as resolved.
Outdated
for (let i = numTypeArguments; i < numTypeParameters; i++) {
result[i] = getConstraintFromTypeParameter(typeParameters![i]) || getDefaultTypeArgumentType(isJavaScriptImplicitAny);
result[i] = instantiateType(getConstraintFromTypeParameter(typeParameters![i]) || baseDefaultType, cicrularityMapper);
}
for (let i = numTypeArguments; i < numTypeParameters; i++) {
const mapper = createTypeMapper(typeParameters!, result);
let defaultType = getDefaultFromTypeParameter(typeParameters![i]);
if (isJavaScriptImplicitAny && defaultType && isTypeIdenticalTo(defaultType, emptyObjectType)) {
defaultType = anyType;
}
result[i] = defaultType ? instantiateType(defaultType, mapper) : getDefaultTypeArgumentType(isJavaScriptImplicitAny);
result[i] = defaultType ? instantiateType(defaultType, mapper) : baseDefaultType;
}
result.length = typeParameters!.length;
return result;
Expand Down
34 changes: 34 additions & 0 deletions tests/baselines/reference/subclassThisTypeAssignable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//// [subclassThisTypeAssignable.ts]
interface Lifecycle<Attrs, State> {
oninit?(vnode: Vnode<Attrs, State>): number;
[_: number]: any;
}

interface Vnode<Attrs, State extends Lifecycle<Attrs, State> = Lifecycle<Attrs, State>> {
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();

//// [subclassThisTypeAssignable.js]
var C = /** @class */ (function () {
function C() {
}
C.prototype.view = function (v) { return 0; };
return C;
}());
var test8 = new C();
92 changes: 92 additions & 0 deletions tests/baselines/reference/subclassThisTypeAssignable.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
=== tests/cases/compiler/subclassThisTypeAssignable.ts ===
interface Lifecycle<Attrs, State> {
>Lifecycle : Symbol(Lifecycle, Decl(subclassThisTypeAssignable.ts, 0, 0))
>Attrs : Symbol(Attrs, Decl(subclassThisTypeAssignable.ts, 0, 20))
>State : Symbol(State, Decl(subclassThisTypeAssignable.ts, 0, 26))

oninit?(vnode: Vnode<Attrs, State>): number;
>oninit : Symbol(Lifecycle.oninit, Decl(subclassThisTypeAssignable.ts, 0, 35))
>vnode : Symbol(vnode, Decl(subclassThisTypeAssignable.ts, 1, 9))
>Vnode : Symbol(Vnode, Decl(subclassThisTypeAssignable.ts, 3, 1))
>Attrs : Symbol(Attrs, Decl(subclassThisTypeAssignable.ts, 0, 20))
>State : Symbol(State, Decl(subclassThisTypeAssignable.ts, 0, 26))

[_: number]: any;
>_ : Symbol(_, Decl(subclassThisTypeAssignable.ts, 2, 2))
}

interface Vnode<Attrs, State extends Lifecycle<Attrs, State> = Lifecycle<Attrs, State>> {
>Vnode : Symbol(Vnode, Decl(subclassThisTypeAssignable.ts, 3, 1))
>Attrs : Symbol(Attrs, Decl(subclassThisTypeAssignable.ts, 5, 16))
>State : Symbol(State, Decl(subclassThisTypeAssignable.ts, 5, 22))
>Lifecycle : Symbol(Lifecycle, Decl(subclassThisTypeAssignable.ts, 0, 0))
>Attrs : Symbol(Attrs, Decl(subclassThisTypeAssignable.ts, 5, 16))
>State : Symbol(State, Decl(subclassThisTypeAssignable.ts, 5, 22))
>Lifecycle : Symbol(Lifecycle, Decl(subclassThisTypeAssignable.ts, 0, 0))
>Attrs : Symbol(Attrs, Decl(subclassThisTypeAssignable.ts, 5, 16))
>State : Symbol(State, Decl(subclassThisTypeAssignable.ts, 5, 22))

tag: Component<Attrs, State>;
>tag : Symbol(Vnode.tag, Decl(subclassThisTypeAssignable.ts, 5, 89))
>Component : Symbol(Component, Decl(subclassThisTypeAssignable.ts, 7, 1))
>Attrs : Symbol(Attrs, Decl(subclassThisTypeAssignable.ts, 5, 16))
>State : Symbol(State, Decl(subclassThisTypeAssignable.ts, 5, 22))
}

interface Component<Attrs, State> {
>Component : Symbol(Component, Decl(subclassThisTypeAssignable.ts, 7, 1))
>Attrs : Symbol(Attrs, Decl(subclassThisTypeAssignable.ts, 9, 20))
>State : Symbol(State, Decl(subclassThisTypeAssignable.ts, 9, 26))

view(this: State, vnode: Vnode<Attrs, State>): number;
>view : Symbol(Component.view, Decl(subclassThisTypeAssignable.ts, 9, 35))
>this : Symbol(this, Decl(subclassThisTypeAssignable.ts, 10, 6))
>State : Symbol(State, Decl(subclassThisTypeAssignable.ts, 9, 26))
>vnode : Symbol(vnode, Decl(subclassThisTypeAssignable.ts, 10, 18))
>Vnode : Symbol(Vnode, Decl(subclassThisTypeAssignable.ts, 3, 1))
>Attrs : Symbol(Attrs, Decl(subclassThisTypeAssignable.ts, 9, 20))
>State : Symbol(State, Decl(subclassThisTypeAssignable.ts, 9, 26))
}

interface ClassComponent<A> extends Lifecycle<A, ClassComponent<A>> {
>ClassComponent : Symbol(ClassComponent, Decl(subclassThisTypeAssignable.ts, 11, 1))
>A : Symbol(A, Decl(subclassThisTypeAssignable.ts, 13, 25))
>Lifecycle : Symbol(Lifecycle, Decl(subclassThisTypeAssignable.ts, 0, 0))
>A : Symbol(A, Decl(subclassThisTypeAssignable.ts, 13, 25))
>ClassComponent : Symbol(ClassComponent, Decl(subclassThisTypeAssignable.ts, 11, 1))
>A : Symbol(A, Decl(subclassThisTypeAssignable.ts, 13, 25))

oninit?(vnode: Vnode<A, this>): number;
>oninit : Symbol(ClassComponent.oninit, Decl(subclassThisTypeAssignable.ts, 13, 69))
>vnode : Symbol(vnode, Decl(subclassThisTypeAssignable.ts, 14, 9))
>Vnode : Symbol(Vnode, Decl(subclassThisTypeAssignable.ts, 3, 1))
>A : Symbol(A, Decl(subclassThisTypeAssignable.ts, 13, 25))

view(vnode: Vnode<A, this>): number;
>view : Symbol(ClassComponent.view, Decl(subclassThisTypeAssignable.ts, 14, 40))
>vnode : Symbol(vnode, Decl(subclassThisTypeAssignable.ts, 15, 6))
>Vnode : Symbol(Vnode, Decl(subclassThisTypeAssignable.ts, 3, 1))
>A : Symbol(A, Decl(subclassThisTypeAssignable.ts, 13, 25))
}

interface MyAttrs { id: number }
>MyAttrs : Symbol(MyAttrs, Decl(subclassThisTypeAssignable.ts, 16, 1))
>id : Symbol(MyAttrs.id, Decl(subclassThisTypeAssignable.ts, 18, 19))

class C implements ClassComponent<MyAttrs> {
>C : Symbol(C, Decl(subclassThisTypeAssignable.ts, 18, 32))
>ClassComponent : Symbol(ClassComponent, Decl(subclassThisTypeAssignable.ts, 11, 1))
>MyAttrs : Symbol(MyAttrs, Decl(subclassThisTypeAssignable.ts, 16, 1))

view(v: Vnode<MyAttrs>) { return 0; }
>view : Symbol(C.view, Decl(subclassThisTypeAssignable.ts, 19, 44))
>v : Symbol(v, Decl(subclassThisTypeAssignable.ts, 20, 6))
>Vnode : Symbol(Vnode, Decl(subclassThisTypeAssignable.ts, 3, 1))
>MyAttrs : Symbol(MyAttrs, Decl(subclassThisTypeAssignable.ts, 16, 1))
}

const test8: ClassComponent<any> = new C();
>test8 : Symbol(test8, Decl(subclassThisTypeAssignable.ts, 23, 5))
>ClassComponent : Symbol(ClassComponent, Decl(subclassThisTypeAssignable.ts, 11, 1))
>C : Symbol(C, Decl(subclassThisTypeAssignable.ts, 18, 32))

49 changes: 49 additions & 0 deletions tests/baselines/reference/subclassThisTypeAssignable.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
=== tests/cases/compiler/subclassThisTypeAssignable.ts ===
interface Lifecycle<Attrs, State> {
oninit?(vnode: Vnode<Attrs, State>): number;
>oninit : (vnode: Vnode<Attrs, State>) => number
>vnode : Vnode<Attrs, State>

[_: number]: any;
>_ : number
}

interface Vnode<Attrs, State extends Lifecycle<Attrs, State> = Lifecycle<Attrs, State>> {
tag: Component<Attrs, State>;
>tag : Component<Attrs, State>
}

interface Component<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
>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>) { return 0; }
>view : (v: Vnode<MyAttrs, Lifecycle<MyAttrs, Lifecycle<{}, {}>>>) => number
>v : Vnode<MyAttrs, Lifecycle<MyAttrs, Lifecycle<{}, {}>>>
>0 : 0
}

const test8: ClassComponent<any> = new C();
>test8 : ClassComponent<any>
>new C() : C
>C : typeof C

24 changes: 24 additions & 0 deletions tests/cases/compiler/subclassThisTypeAssignable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
interface Lifecycle<Attrs, State> {
oninit?(vnode: Vnode<Attrs, State>): number;
[_: number]: any;
}

interface Vnode<Attrs, State extends Lifecycle<Attrs, State> = Lifecycle<Attrs, State>> {
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();