typescript: строка утверждения не является частью объединения

#typescript

#typescript

Вопрос:

Я хочу, чтобы typescript утверждал, что «новая» строка не является частью объединения, существующего набора, в который будет добавлена строка.

Я ищу независимую, отдельную строку кода, но это просто приятно иметь.

Итак, простая, хотя и надуманная ситуация:

 type FruitOptions = 'banana' | 'apple' | 'grape'
type NewFruitOption = 'pear'
// ^ being passed into a function ^

// Assert: FruitOptions does not contain NewFruitOption
 

Я не думаю, что совместное использование этого необходимо, но это служебная функция, в которой я пытаюсь использовать эту технику:

 // These are inferred generics (since they come after the = sign), do not pass them in.
export const renameKey = <
  OldKey extends keyof T,
  NewKey extends string, // should NOT already be keyof T
  T extends Record<string, unknown>
>(
  oldKey: OldKey,
  newKey: NewKey,
  userObject: T
): Record<NewKey, T[OldKey]> amp; Omit<T, OldKey> => {
  const { [oldKey]: value, ...common } = userObject

  return {
    ...common,
    ...({ [newKey]: value } as Record<NewKey, T[OldKey]>)
  }
}
 

Ответ №1:

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

 newKey: NewKey extends keyof T ? never : NewKey
 

Когда вы затем измените этот допустимый вызов:

 renameKey('lastName', 'clientLastName', formData)
 

Быть недействительным:

 renameKey('lastName', 'lastName', formData)
 

Вы получите красное подчеркивание на втором 'lastName' высказывании: Argument of type 'string' is not assignable to parameter of type 'never'. ts(2345) . Также произойдет сбой, если вы попытаетесь переименовать ключ в любой другой ключ, который уже существует:

 renameKey('lastName', 'dateOfBirth', formData)
 

ошибка, показанная внутри vscode