-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Mixins typing works with inference but not with explicit types #16089
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I am not able to reproduce this locally. please provide a self contained reproduction of the issue in question. c:\test\sandbox>type a.ts
class Person {
constructor(public name: string) {}
}
type Constructor<T> = new(...args: any[]) => T;
interface MixinFn<MixinInterface> {
<T extends Constructor<{}>>(superclass: T): Constructor<MixinInterface> & T;
}
interface Tagable {
tag: (tag: string) => void;
}
// Why doesn't this work?
type TagableMxinFn = MixinFn<Tagable>;
// Impossible to drop typing for T
// results in an error with --strict (superclass is any)
// and further error on extends saying that T should be of type a constructor
const Tagable: TagableMxinFn = <T extends Constructor<{}>>(superclass: T) => {
return class extends superclass {
// no typechecking of rerturn type; must use implements
}
};
const TagablePerson = Tagable(Person);
let foo = new TagablePerson('a');
foo.tag("");
// While this does
// the other way of acheiving the same typing is to remove return type
// `: Constructor(Tagable) & T`
// and specify `implements` Tagable in the class expression.
function Tagable2<T extends Constructor<{}>>(superclass: T):
Constructor<Tagable> & T {
return class extends superclass {
// implements Tagable is enforced here
// commenting out the next line results in an appropriate error
tag(tag: string) {}
}
}
const Tagable2Person = Tagable2(Person);
let bar = new Tagable2Person('s');
bar.name;
bar.tag('s'); // all good, autocompleted and checked
// Bonus: this is valid.
const TagableScam: TagableMxinFn = () => {};
export {};
c:\test\sandbox>tsc --v
Version 2.3.3
c:\test\sandbox>tsc a.ts
c:\test\sandbox>echo %ERRORLEVEL%
0 |
The point here is that So should // and further error on extends saying that T should be of type a constructor
const Tagable: TagableMxinFn = <T extends Constructor<{}>>(superclass: T) => {
return class extends superclass {
// no typechecking of rerturn type; must use implements
}
}; since the return value doesn't implement Tagagble, and once that is being checked, this should not break with --strict: const Tagable2: MixinFn<Tagable> = (superclass) => {
return class extends superclass {
// implements Tagable is enforced here
// commenting out the next line results in an appropriate error
tag(tag: string) {}
}
}; |
i see. for the |
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed. |
Does it mean that what I described is supposed TS behavior (namely, inference behavior being impossible to code in types)?! |
Not sure i understand the issue at this point. can you provide some explanation and why not the same as . #5616. |
I misunderstood the automatically closed message. It does look like #5616 should fix it. |
TypeScript Version: 2.3.1
Code
Expected behavior:
conext: #13743 (comment)
superclass
argument without explicit providing a generic typing for it.Actual behavior:
i.e.
{ new(...args: any[]) => A } & { new(s: string) => B }
doesn't seem to hold true.as far as I can tell typing a function with MixinFn does nothing.
The text was updated successfully, but these errors were encountered: