-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Allow for static members to reference class type parameters (Error: TS2302) #32211
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
If so, then what type is This is basically the first question in #24018, and I can't see how you have answered it yet. |
The type would be provided by the subclass i.e.: class Amount extends Column<Bigint> { // <— here the generic type is provided
static readonly _name: string = '"amt"';
// (inherited) static readonly dataType: typeof T = T; // hence this would be `typeof Bigint = Bigint`
} |
I realise your intent, but what I am trying to say is that it does not make sense with existing TS patterns. There is nothing about class Basically, at the point of consuming If your proposal is "Allow for static members to reference class type parameters, defaulting to |
Hold on. Apologies, I was wrong about the use of How about the below? import Big from 'big.js';
interface ICtor {
new (...args: any[]) : {};
}
// db column
class Column<T> { // T doesn’t need defaulting as `{} as T` defaults to `{}` even if T is a non-object primitive
static readonly _name: string;
static readonly comment: string;
static readonly dataType: ICtor = ({} as T).constructor; // error: Static members cannot reference class type parameters ts(2302)
constructor(readonly value: T) {}
}
class Bigint {
constructor(readonly value: Big = new Big(0)) {}
}
class Amount extends Column<Bigint> {
static readonly _name: string = '"amt"';
//static readonly dataType: ICtor = ({} as Bigint).constructor; // this would be unnecessary
}
class Quantity extends Column<BigInt> {
static readonly _name: string = '"qty"';
//static readonly dataType: ICtor = ({} as Bigint).constructor; // this would be unnecessary
} |
@geoyws You still seem to be misunderstanding. You cannot use a type to get a constructor for the type. Furthermore, So you could never take a generic parameter To solve the case you've described, you could use mixins like so: type Constructor<T, Args extends any[] = any[]> = new (...args: Args) => T;
export interface ColumnConstructor<T> {
readonly _name: string;
readonly comment: string;
readonly dataType: Constructor<T>;
new (value: T): Column<T>;
}
interface Column<T> {
readonly value: T;
}
function Column<T>(dataType: Constructor<T>): ColumnConstructor<T> {
return class Column {
static readonly _name: string;
static readonly comment: string;
static readonly dataType = dataType;
constructor(readonly value: T) {}
};
}
class Bigint {
constructor(readonly value: Big = new Big(0)) {}
}
class Amount extends Column(Bigint) {
static readonly _name: string = '"amt"';
}
class Quantity extends Column(Bigint) {
static readonly _name: string = '"qty"';
} |
Yeah, I don't see how this can work. Until an instance of the class (or an instance of a subclass) is constructed, you don't actually have a type |
Every attempt to do this ultimately originates in a conceptual confusion. Critically, the constructor object for a generic class is not generic -- it contains generic construct signatures, which is a completely different thing. |
@fatcerberus @RyanCavanaugh thanks for your time guys. I was thinking perhaps TS could implement this via a class factory that churns out custom constructor functions fitted with the static properties and methods. @superamadeus appreciate the clarification very much. |
You can certainly do something like that for yourself and typescript will typecheck it. But any idea of typescript automatically inserting a factory like this and then calling it with different values each time you use a generic class with different parameters is type directed emit and out of scope. |
It's also not what ES6 does. |
So it’s because TS’ design goals prohibit her from doing type directed emit. That explains things. Thanks for the explanation guys. |
This is actually possible to do but with a lot of jumping around. class C_<T> {
// static myStatic: T;
}
interface Ctor {
myStatic: this extends typeof C_<infer T> ? T : never;
}
const C: typeof C_ & Ctor = C_ as any;
C.myStatic; // unknown
C<number>.myStatic; // number Admittedly, it might not make any sense for a static property like this. But it can be very useful for say, a parameter of a static method. So if it is after all possible, it might as well be allowed with the simpler syntax and save us the hassle. |
Search Terms
Suggestion
Allow for static members to reference class type parameters because it saves typing.
Perhaps we could use a factory to dynamically create classes based on the generic type provided.
Use Cases
Examples
See previous section.
Checklist
My suggestion meets these guidelines:
The text was updated successfully, but these errors were encountered: