我想确保类型A具有通用类型的字段,但是该字段的名称由来自另一个对象的字段的值定义。
例如功能:
interface IndexedContext<K extends string, T> {
context: T;
key: K;
}
type TypeB<P, K, T> = {
// this field should be named after IndexedContext[key]
P[K] = T;
}
const Consumer =
<T extends object, K>(context: IndexedContext<K, T>) => <C extends ComponentType<TypeA>, TypeA extends TypeB: C => {
.....
};
TypeA(属性)应该具有一个字段,该字段是IndexedKey中字段键的值吗?这样,当我在react组件上使用此装饰器并向其传递ReactContext时,我可以确保道具具有与键相同的字段。
@Consumer({context: MyContext, key: 'myKey'})
class MyClass extends Component<MyProps> {}
interface MyProps {
// compiler should fail if this key is missing.
myKey: // Type of value of MyContext
}
答案 0 :(得分:0)
您无需定义任何额外的mapped types(例如您示例中的TypeB
),则可以使用Record
从字符串文字中获取映射类型,然后字段类型。
您还需要捕获实例类型而不是构造函数。如果您写{context: MyContext, key: 'myKey'}
,则context
将是类MyContext
,因此T
将被推断为typeof MyContext
而不是MyContext
。要获取实例类型,您可以将context
键入为new (...a:any[]) => T
。
将它们放在一起:
interface IndexedContext<K extends string, T> {
context: Type<T>;
key: K;
}
type Type<T> = new (...a: any[]) => T
const Consumer =
<T extends object, K extends string>(context: IndexedContext<K, T>) => <C extends ComponentType<Record<K, T>>>(cls: C) => {
};
class MyContext { }
@Consumer({ context: MyContext, key: 'myKey' })
class MyClass extends Component<MyProps> { }
interface MyProps {
// compiler WILL fail if this key is missing.
myKey: MyContext// Type of value of MyContext
}
注意,context
必须为此工作分配一个类,您将无法直接使用接口或原语。