Как ограничить keyof T только строковыми ключами? - PullRequest
0 голосов
/ 23 января 2020

Я пытаюсь расширить существующий интерфейс:

type ColDef = { field: string; }

, чтобы ограничить значения полей только фактическими свойствами указанного типа:

interface TypeSafeColDef<T> extends ColDef {
   field: keyof T
}

, но я получаю :

Интерфейс 'TypeSafeColDef' неправильно расширяет интерфейс 'ColDef'. Типы свойства 'field' несовместимы. Введите 'keyof TRow | undefined «нельзя назначить типу» string | не определено. Тип 'keyof TRow' нельзя назначить типу 'string | не определено. Тип 'строка | номер | символ «нельзя назначить типу» string | не определено. Тип «число» нельзя назначить типу «строка» | не определено. Тип 'keyof TRow' нельзя назначить типу 'string'. Тип 'строка | номер | Символ 'не может быть назначен типу' строка '. Тип «число» нельзя назначить типу «строка»

Я пробовал следующее ограничение, но безуспешно

type StringKey = { [key: string]: any }

interface TypeSageColDef<TRow extends StringKey>

1 Ответ

0 голосов
/ 23 января 2020

Ваш последний подходит довольно близко, нам все еще нужно расширить ColDef и извлечь string тип ключа для field:

type ColDef = { field: string; }

interface TypeSafeColDef<T extends object> extends ColDef {
  field: Extract<keyof T, string>
}

// test
type T1 = TypeSafeColDef<{ a: string }> // { field: "a"; }

field теперь имеет тип Extract<keyof T, string>, потому что keyof поддерживает string | number | symbol имена свойств , начиная с TS 2.9 . Существует опция компилятора --keyofStringsOnly, чтобы отключить это новое поведение, если вы этого не хотите.

Второй альтернативой является определение псевдонима типа, чтобы избавиться от Extract , Это работает из-за характера оператора пересечения , никогда не вызывающего ошибок :

type TypeSafeColDefAlias<T extends object> = ColDef & {
  field: keyof T
}

Пример кода

...