You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
TS is overly picky when declaring a class constructor type #29707
In the pull request the rest parameter of any[] is required:
In the following, the term mixin constructor type refers to a type that has a single construct signature with a single rest argument of type any[] and an object-like return type.
Not saying it should be but this is the expected behavior, unknown along came a long time after this PR, maybe the rules can be changed.
Ryan Cavanaugh (@RyanCavanaugh) So the issue seems ridiculously easy to fix (and I have the code ready), I was just wondering how to go about the tests. Should I add a new one or change one to include a version with unknown[] (this seems like a good candidate conformance/classes/mixinClassesAnnotated.ts)
The constraint new(...args: unknown[]) => {} works well as long as strictFunctionTypes are not turned on. When that flag is on this code becomes an error
classBase{constructor(publicx: number,publicy: number){}}letc : new(...args: unknown[])=>{}=Base// error under strictFunctionTypes: truenewc("")// runtime type mismatch
This means that you can't really call the mixin with anything but an empty constructor or one that has unknown arguments.
Ryan Cavanaugh (@RyanCavanaugh) I can look into that, but this problem seems much bigger than mixins and would have implications broadly. Rest parameters of type unknown[] are generally not compatible with arbitrary parameter types even if we are talking about a constraint. This currently fails under strictFunctionTypes
functiontest<Textends(...a: unknown[])=>unknown>(fn:T) : T{fn("");// this passes "" can be assigned to unknown returnfn;}test(function(a: number){// error here under strictFunctionTypes})
I'm not 100% sure it is necessarily a great idea to make the code above error free . It seems to be weaker as far as type safety goes. As we see in the code above the callback passed in accepts a number but it's called inside test with a string. I think the current behavior is better, don't let a function with a number parameter be assigned to a function with an unknown parameter, the implementing function can't handle unknown.
While this is no worse than if we use any[], unknown[] would give a false sense of type-safety when no safety actually exists. Except for obeying the no-any tslint rule not sure why unknown is better in this instance. At least any would function as a '💀💀 careful unsafe 💀💀' warning, at least that's the way I see any :)
The problem isn't specific to constructors or rest parameters, it's just that function types are contravariant in their parameter types. You only run into this inverted subtyping relation when you, for example, pass a function as a parameter to another function, as you do with mixins.
unknown is one of the widest types, and so will be the most restrictive when used as a function parameter type. For the function type to be as wide as possible, the parameter type must be as narrow as possible. any works because, while it's the widest type, it's also one of the narrowest. The counterintuitive conclusion is that the type of ...args should be never[].
I ran into this problem today when I needed to describe a type that would fit the right operand of instanceof. Since the code had no business in actually calling the constructor, never[] did the trick. For mixins, however, it seems like they need to take the constructor in, as well as return an interface based off it. With my limited TS experience, I don't see any other way of achieving this than with any.
I'm interested in working on this issue. Could you provide more context about what you're looking for? Any additional details about requirements or constraints would be helpful.
Activity
dragomirtitian commentedon Feb 3, 2019
In the pull request the rest parameter of
any[]is required:Not saying it should be but this is the expected behavior,
unknownalong came a long time after this PR, maybe the rules can be changed.RyanCavanaugh commentedon Feb 4, 2019
Agree,
unknown[]should be an acceptable substitute. Accepting PRs for an easy fix.dragomirtitian commentedon Feb 4, 2019
Ryan Cavanaugh (@RyanCavanaugh) So the issue seems ridiculously easy to fix (and I have the code ready), I was just wondering how to go about the tests. Should I add a new one or change one to include a version with
unknown[](this seems like a good candidateconformance/classes/mixinClassesAnnotated.ts)RyanCavanaugh commentedon Feb 4, 2019
Titian Cernicova-Dragomir (@dragomirtitian) no preference; whichever's easiest for you
dragomirtitian commentedon Feb 4, 2019
Ryan Cavanaugh (@RyanCavanaugh) I added a fix, just one problem (which unfortunately probably makes my fix almost useless).
The constraint
new(...args: unknown[]) => {}works well as long asstrictFunctionTypesare not turned on. When that flag is on this code becomes an errorThis means that you can't really call the mixin with anything but an empty constructor or one that has
unknownarguments.RyanCavanaugh commentedon Feb 4, 2019
That's why it's a constraint (not a concrete type) though, right?
dragomirtitian commentedon Feb 5, 2019
Ryan Cavanaugh (@RyanCavanaugh) I can look into that, but this problem seems much bigger than mixins and would have implications broadly. Rest parameters of type
unknown[]are generally not compatible with arbitrary parameter types even if we are talking about a constraint. This currently fails understrictFunctionTypesI'm not 100% sure it is necessarily a great idea to make the code above error free . It seems to be weaker as far as type safety goes. As we see in the code above the callback passed in accepts a
numberbut it's called insidetestwith astring. I think the current behavior is better, don't let a function with anumberparameter be assigned to a function with anunknownparameter, the implementing function can't handleunknown.While this is no worse than if we use
any[],unknown[]would give a false sense of type-safety when no safety actually exists. Except for obeying theno-anytslint rule not sure whyunknownis better in this instance. At leastanywould function as a '💀💀 careful unsafe 💀💀' warning, at least that's the way I seeany:)jszopi commentedon Jul 23, 2022
The problem isn't specific to constructors or rest parameters, it's just that function types are contravariant in their parameter types. You only run into this inverted subtyping relation when you, for example, pass a function as a parameter to another function, as you do with mixins.
unknownis one of the widest types, and so will be the most restrictive when used as a function parameter type. For the function type to be as wide as possible, the parameter type must be as narrow as possible.anyworks because, while it's the widest type, it's also one of the narrowest. The counterintuitive conclusion is that the type of...argsshould benever[].I ran into this problem today when I needed to describe a type that would fit the right operand of
instanceof. Since the code had no business in actually calling the constructor,never[]did the trick. For mixins, however, it seems like they need to take the constructor in, as well as return an interface based off it. With my limited TS experience, I don't see any other way of achieving this than withany.Fix: Correct constructor type inference in checker.ts (microsoft#29707).
tysoncung commentedon Oct 7, 2025
I'm interested in working on this issue. Could you provide more context about what you're looking for? Any additional details about requirements or constraints would be helpful.
alisa-xh commentedon Apr 14, 2026
👋 你好!
我是专业开发者,专注于开源项目贡献。
我可以帮你:
经验:
合作方式:
请加微信详谈:qmyc-01(备注GitHub)
期待合作!
RyanCavanaugh commentedon Apr 15, 2026
snarbles2 I'm tempted to set up a script to auto-ban anyone who gets a 🚀 reaction from you 😅
LeonxLJX commentedon Sep 1, 2026
I'd like to take this one — I'll follow up with a PR. (claiming via Stella (@LeonxLJX))
LeonxLJX commentedon Sep 1, 2026
Hi! I'd like to fix the overly-picky constructor type check. Plan: reproduce, adjust the check, add a test. May I be assigned?