reactjs - 确保类型 A 扩展具有字段且该字段是另一个对象的值的类型 B
我想确保类型 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(props)应该有一个字段,它的值是 IndexedKey 中的字段 key?这样当我在一个 React 组件上使用这个装饰器并传递一个 ReactContext 给它时,我就可以确保 props 有一个与 key 相同的字段。
@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
}
答案#1
你不需要定义任何额外的映射类型(例如在你的示例中应该有的 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 必须被分配一个类才能生效,你将无法直接使用接口或基本类型。
