确保类型A扩展了类型B,该类型B的字段是另一个对象的值

时间:2018-11-19 13:46:32

标签: reactjs typescript

我想确保类型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
}

1 个答案:

答案 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必须为此工作分配一个类,您将无法直接使用接口或原语。

相关问题