-
Notifications
You must be signed in to change notification settings - Fork 12.8k
[Feature Request] Allow Class Index Signatures to be mapped #49509
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
This is possible today, it just requires a weirder syntax type Tmp = { [key in keyof Config]: Config[key]; }
interface Foo extends Tmp { }
// OK
new Foo(null as any).func1?.() |
@RyanCavanaugh cool didnt know about that, the syntax does feel a bit hacky but atleast I think I can use this for now |
class A<const T extends {[key: PropertyKey]: any}> {
constructor(props: T) {
Object.assign(this, props);
}
[K in keyof T]: T[K]
}
const a = new A({
key1: 42
});
console.log(a.key1) there is solution: class __A {
constructor(props: {[key: PropertyKey]: any}) {
Object.assign(this, props);
}
}
interface __AConstructor {
new <const T extends {[key: PropertyKey]: any}>(props: T): __A & T;
}
const A = __A as __AConstructor;
const a = new A({
key1: 42
});
console.log(a.key1) |
It's nice to see the topic for 2022, to a problem that has not been solved. I can't just call Object.assign(this, ...) and get the types in the class, because the class can't be extended from the object. Although it's very funny, considering that in js - literally everything is an object... |
Would this be difficult to implement? class Foo {
// this breaks for two reasons:
// 1. mapped fields doesn't exist yet
// 2. afaik this[K] doesn't work even in non-mapped fields like: qux = {} as { [K as keyof this]: this[K] }
{ [K in keyof this as `$${K & string}`]: this[K] };
bar = 1;
constructor() {
for (const [key, value] of Object.entries(this)) {
Object.defineProperty(this, '$' + key, { value });
}
this.$bar // now we can use this in constructors
}
qux() {
this.$bar // and methods
}
}
const foo = new Foo();
foo.$bar // and externally |
Suggestion
🔍 Search Terms
List of keywords you searched for before creating this issue. Write them down here so that others can find this suggestion more easily and help provide feedback.
"mapped class members", "mapped class index signature"
✅ Viability Checklist
My suggestion meets these guidelines:
⭐ Suggestion
We can define index signatures for classes, ie https://www.typescriptlang.org/docs/handbook/2/classes.html#index-signatures, however, these signatures can not be mapped from an existing type, as can be done for object type aliases. It would be useful if similar behavior existed for classes to allow members of a class to be defined based on an existing type.
📃 Motivating Example
I am working on typing some existing JS code (can't be changed) that has classes that take in a config in the constructor and then spreads the config into the instance, which means I need to define a type for the config, then define each property of the config as a declare member on the class to get the typing to work, eg:
However, this is quite tedious and if the configs are significant or have external dependencies then it can be easy to have the Config type out of sync with the manually declared members.
I have made some code examples of what I think would be good here
ie the following should work in terms of showing intellisense for and allowing usage of the mapped members from Config with correct types on class instances:
Related to
The text was updated successfully, but these errors were encountered: