Создать объект с именем и типизированным значением свойства типа - PullRequest
1 голос
/ 19 июня 2020

Учитывая следующие типы:

export interface PatchOperation<T> {
  from?: keyof T;
  op: OperationType;
  path: keyof T;
  value?: T[keyof T];
}

interface Parent {
  creation: Date;
  id: number;
  name: string;
}

Как я могу обеспечить, чтобы PatchOperation<Parent>.value имел правильный тип для PatchOperation<Parent>.path.

Чтобы приведенный ниже код генерировал ошибку:

const update: PatchOperation<Parent> = {
  op: OperationType.Replace,
  path: 'creation',
  value: 'string', // Type 'string' is not assignable to type 'Date'.
};

Ответы [ 2 ]

1 голос
/ 19 июня 2020

Ваше решение можно улучшить, используя условный тип дистрибутива , поэтому вам не нужно явно передавать тип ключа:

export type PatchOperation<T, K = keyof T> = K extends keyof T ? {
  op: OperationType;
  path: K;
  value?: T[K];
} : never;

Теперь мы получаем ожидаемую ошибку:

// Type 'string' is not assignable to type 'Date | undefined'
const update: PatchOperation<Parent> = {
  op: OperationType.Replace,
  path: 'creation',
  value: 'string',
};

Распределительные условные типы автоматически распределяются по типам union во время создания экземпляра

Таким образом, в нашем примере PatchOperation<Parent> будет эквивалентно:

{
    op: OperationType;
    path: "creation";
    value?: Date;
} | {
    op: OperationType;
    path: "id";
    value?: number;
} | {
    op: OperationType;
    path: "name";
    value?: string;
}

Детская площадка

0 голосов
/ 19 июня 2020

Не так практично, как хотелось бы, но работает, добавляя второй параметр generi c, соответствующий названию свойства.

export interface PatchOperation<T, P extends keyof T> {
  from?: keyof T;
  op: OperationType;
  path: keyof T;
  value?: T[P];
}

interface Parent {
  creation: Date;
  id: number;
  name: string;
}

const update: PatchOperation<Parent, 'creation'> = {
  op: OperationType.Replace,
  path: 'creation',
  value: 'string', // Type 'string' is not assignable to type 'Date'.ts(2322)
};

const update: PatchOperation<Parent, 'creation'> = {
  op: OperationType.Replace,
  path: 'creation',
  value: new Date(), // ok
};

Практическое использование:

type PatchDocument<T, P extends keyof T> = PatchOperation<T, P>[];

const update = createAction(
    '[Project] Update Project',
    props<{
      operation : PatchDocument<ProjectDTO, keyof ProjectDTO>
    }>()
  );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...