【问题标题】:How to replace properties using mapped types in Typescript如何在 Typescript 中使用映射类型替换属性
【发布时间】:2018-10-26 15:02:04
【问题描述】:

我有一个接收对象的工厂函数,如果该对象具有特定名称的属性,工厂会将这些属性转换为方法。

如何使用映射类型正确表示输出对象的类型?

例如,假设可转换属性为 foo、bar、baz:

interface IFactoryConfig {
   foo?: string;
   bar?: string;
   baz?: string;
}

替换属性为:

interface IFactoryResult {
   foo(someParam: string): boolean;
   bar(): number;
   baz(otherParam: number): void;
}

如果输入的类型是

interface IInputObject {
   baz: string;
   notPredefined: string;
   aNumber: number;
   foo: string;
   aMethod(): void;
}

工厂用方法替换baz和foo并返回:

interface IInputObject {
   baz(otherParam: number): void;
   notPredefined: string;
   aNumber: number;
   foo(someParam: string): boolean;
   aMethod(): void;
}

我正在尝试使用映射类型来替换属性:

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

interface IFactory {
   <InputType extends IFactoryConfig, ResultType>(config: InputType): Omit<InputType, keyof IFactoryConfig> & Pick<IFactoryResult, ?>;
}

我不知道在 Pick 中放入什么以从 IFactoryResult 中选择也出现在 InputType 上的属性。

【问题讨论】:

    标签: typescript mapped-types


    【解决方案1】:

    我们在这里只讨论类型级别的东西,而不是运行时行为。您可以在映射类型中使用 conditional types 来执行检查。这是一个通用的属性替换器:

    type ReplaceProps<T, From, To> = { [K in keyof T]:
      K extends keyof From ? T[K] extends From[K] ? K extends keyof To ? To[K] 
      : T[K] : T[K] : T[K]
    }
    

    这个想法是T中的任何属性,其键和值类型也在From中找到并且其键在To中找到,将被To中的属性类型替换;否则它会独自留下财产。

    那么你可以这样使用它:

    type IInputObjectOut = ReplaceProps<IInputObject, IFactoryConfig, IFactoryResult>;
    

    并检查IInputObjectOut,您会发现它与您想要的类型匹配:

    type IInputObjectOut = {
      baz: (otherParam: number) => void;
      notPredefined: string;
      aNumber: number;
      foo: (someParam: string) => boolean;
      aMethod: () => void;
    }    
    

    认为您可以像这样定义您的 IFactory 类型,假设它应该是可调用的并且其输入类型的行为类似于 ReplaceProps

    interface IFactory {
      <T>(config: T): ReplaceProps<T, IFactoryConfig, IFactoryResult>;
    }
    
    declare const iFact: IFactory;
    declare const input: IInputObject;
    input.foo; // string
    input.aNumber; // number
    const output = iFact(input); // ReplaceProps<IInputObject, IFactoryConfig, IFactoryResult>;
    output.foo("hey"); // boolean
    output.aNumber; // number
    

    这对你有用吗?希望能帮助到你。祝你好运!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-30
      • 1970-01-01
      • 1970-01-01
      • 2021-09-16
      • 1970-01-01
      • 1970-01-01
      • 2018-06-25
      • 2018-08-28
      相关资源
      最近更新 更多