Как заменить свойства, используя сопоставленные типы в Typescript - PullRequest
0 голосов
/ 26 октября 2018

У меня есть функция Factory, которая получает объект, и если этот объект имеет свойства с определенным именем, фабрика преобразует эти свойства в методы.

Как я могу использовать сопоставленные типы, чтобы правильно представлять тип объекта?объект вывода?

Например, допустим, что конвертируемыми свойствами являются 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.

1 Ответ

0 голосов
/ 26 октября 2018

Мы просто говорим о вещах на уровне типов, а не о поведении во время выполнения.Вы можете использовать условные типы внутри вашего сопоставленного типа для выполнения проверки.Вот заменитель общего свойства:

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

Делает ли эторабота для тебя?Надеюсь, поможет.Удачи!

...