如何在 Typescript 中使用映射类型替换属性

How to replace properties using mapped types in Typescript

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

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

例如,假设可转换属性为 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;
}

工厂用methods替换baz和foo returns:

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, ?>;
}

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

我们这里只讨论类型级的东西,而不是 运行 时间行为。您可以在映射类型中使用 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

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