使用与其他键相同的键声明对象
Declare object with same keys as other
我想声明一个对象到另一个对象的映射。
第一个对象可以有泛型类型的任何字符串键和值。
我想用相同的键映射这个对象,值的类型可以是任何类型(但如果我能从泛型中提取它们就好了)。具体来说,这些是 class 的属性,第一个在构造函数中传递。
class C {
ob1: {
[key: string]: Wrapper<any>
};
ob2; // should have the same keys as ob1
constructor(o?: { [key: string]: Wrapper<any> }) {
this.ob1 = o;
// map ob2 from o
}
}
我认为这样做的方法是使 C
本身成为 generic class with a type parameter T
corresponding to either the type of ob1
or ob2
, and then use mapped types 来表达“相同的键但 different/related 值”。例如:
type MappedWrapper<T> = { [K in keyof T]: Wrapper<T[K]> }
class C<T> {
ob1: MappedWrapper<T>
ob2: T;
constructor(o: MappedWrapper<T>) { // made param required here
this.ob1 = o;
this.ob2 = mapUnwrap(o); // some function that unwraps properties
}
}
这里我们说 T
是 ob2
的类型,而 ob1
的类型是 MappedWrapper<T>
,一个映射类型,其中每个 属性 ob1
映射到 Wrapper
版本。
取决于Wrapper
及相关类型的实现和声明,如:
type Wrapper<T> = { x: T };
function wrap<T>(x: T): Wrapper<T> {
return { x };
}
function unwrap<T>(x: Wrapper<T>): T {
return x.x;
}
function mapUnwrap<T>(x: MappedWrapper<T>): T {
return Object.fromEntries(Object.entries(x).map(([k, v]) => [k, unwrap(v)])) as any as T;
}
您可以验证这是否按预期工作:
const c = new C({ a: wrap(123), b: wrap("hello"), c: wrap(true) });
/* const c: C<{ a: number; b: string; c: boolean;}> */
c.ob1.a.x.toFixed(); // no error
c.ob2.b.toUpperCase(); // no error
我想声明一个对象到另一个对象的映射。
第一个对象可以有泛型类型的任何字符串键和值。
我想用相同的键映射这个对象,值的类型可以是任何类型(但如果我能从泛型中提取它们就好了)。具体来说,这些是 class 的属性,第一个在构造函数中传递。
class C {
ob1: {
[key: string]: Wrapper<any>
};
ob2; // should have the same keys as ob1
constructor(o?: { [key: string]: Wrapper<any> }) {
this.ob1 = o;
// map ob2 from o
}
}
我认为这样做的方法是使 C
本身成为 generic class with a type parameter T
corresponding to either the type of ob1
or ob2
, and then use mapped types 来表达“相同的键但 different/related 值”。例如:
type MappedWrapper<T> = { [K in keyof T]: Wrapper<T[K]> }
class C<T> {
ob1: MappedWrapper<T>
ob2: T;
constructor(o: MappedWrapper<T>) { // made param required here
this.ob1 = o;
this.ob2 = mapUnwrap(o); // some function that unwraps properties
}
}
这里我们说 T
是 ob2
的类型,而 ob1
的类型是 MappedWrapper<T>
,一个映射类型,其中每个 属性 ob1
映射到 Wrapper
版本。
取决于Wrapper
及相关类型的实现和声明,如:
type Wrapper<T> = { x: T };
function wrap<T>(x: T): Wrapper<T> {
return { x };
}
function unwrap<T>(x: Wrapper<T>): T {
return x.x;
}
function mapUnwrap<T>(x: MappedWrapper<T>): T {
return Object.fromEntries(Object.entries(x).map(([k, v]) => [k, unwrap(v)])) as any as T;
}
您可以验证这是否按预期工作:
const c = new C({ a: wrap(123), b: wrap("hello"), c: wrap(true) });
/* const c: C<{ a: number; b: string; c: boolean;}> */
c.ob1.a.x.toFixed(); // no error
c.ob2.b.toUpperCase(); // no error