Что Record<K, T>
значит в Typescript?
Typescript 2.1 представил Record
тип, описав его в примере:
// For every properties K of type T, transform it to U function mapObject<K extends string, T, U>(obj: Record<K, T>, f: (x: T) => U): Record<K, U>
см. Typescript 2.1
И Advanced Типы страницы упоминается Record
под отображенных типов заголовков вместе Readonly
, Partial
и Pick
, в том, что , как представляется, его определение:
type Record<K extends string, T> = { [P in K]: T; }
Только для чтения, Partial и Pick гомоморфны, а Record - нет. Один признак того, что Record не является гомоморфным, заключается в том, что для копирования свойств не требуется тип ввода:
type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>
И это все. Помимо приведенных выше цитат, нет других упоминаний Record
о typescriptlang.org .
Вопросы
Может кто-нибудь дать простое определение того, что
Record
есть?Это
Record<K,T>
просто способ сказать "все свойства этого объекта будут иметь типT
"? Вероятно, не все свойства, так какK
имеет какое-то назначение ...Запрещает ли
K
общий тип дополнительные ключи на объекте, которые не являютсяK
, или он разрешает их и просто указывает, что их свойства не преобразованы вT
?С приведенным примером:
type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>
Это точно так же, как это?
type ThreeStringProps = {prop1: string, prop2: string, prop3: string}
источник
Ответы:
A
Record<K, T>
- это тип объекта, ключиK
свойства которого имеют значения свойстваT
. То естьkeyof Record<K, T>
эквивалентноK
иRecord<K, T>[K]
(в основном) эквивалентноT
.Как вы заметили,
K
имеет цель ... ограничить ключи свойств конкретными значениями. Если вы хотите принять все возможные строковые ключи, вы можете сделать что-то подобноеRecord<string, T>
, но идиоматический способ сделать это - использовать сигнатуру индекса как{ [k: string]: T }
.Это не совсем «запрещает» дополнительные ключи: в конце концов, как правило, значение может иметь свойства, явно не упомянутые в его типе ... но оно не признает, что такие свойства существуют:
и это будет относиться к ним как к лишним свойствам, которые иногда отвергаются:
и иногда принимаются:
Да!
Надеюсь, это поможет. Удачи!
источник
Record<string, V>
чтобы означать,{[x: string]: V}
если вы хотите; Я, наверное, даже сделал это сам. Версия подписи индекса более прямолинейна: они одного типа, но первая является псевдонимом типа сопоставленного типа, который оценивает подпись индекса, тогда как последняя напрямую является только подписью индекса. При прочих равных я бы порекомендовал последнее. Точно так же я бы не использовалRecord<"a", string>
вместо,{a: string}
если бы не было какой-то другой убедительной контекстной причины, чтобы сделать это.Record<string, V>
имеет смысл, только если вы уже знаете, как подписи индекса работают в TypeScript. Например, учитываяx: Record<string, string>
,x.foo
очевидно, будетstring
во время компиляции, но в действительности, вероятно, будетstring | undefined
. Это пробел в том, как--strictNullChecks
работает (см. # 13778 ). Я предпочел бы иметь дело с новичками{[x: string]: V}
непосредственно вместо того , чтобы ожидать их по цепочке отRecord<string, V>
по{[P in string]: V}
поведению индекса подписи.Запись позволяет вам создать новый тип из Союза. Значения в Union используются как атрибуты нового типа.
Например, скажем, у меня есть Союз, подобный этому:
Теперь я хочу создать объект, который содержит информацию обо всех кошках, я могу создать новый тип, используя значения в Союзе CatName в качестве ключей.
Если я хочу удовлетворить этот CatList, я должен создать такой объект:
Вы получаете очень сильный тип безопасности:
Реальный пример React.
Я использовал это недавно, чтобы создать компонент Status. Компонент получит реквизит состояния, а затем отобразит значок. Я очень упростил код здесь для наглядности
У меня был такой союз:
Я использовал это, чтобы создать объект, подобный этому:
Затем я могу сделать рендеринг, разложив элемент из объекта в подпорки, например, так:
Если объединение «Статусы» будет позже расширено или изменено, я знаю, что мой компонент «Статус» не удастся скомпилировать, и я получу ошибку, которую можно исправить немедленно. Это позволяет мне добавлять дополнительные состояния ошибок в приложение.
Обратите внимание, что в настоящем приложении были десятки состояний ошибок, на которые ссылались в нескольких местах, поэтому безопасность этого типа была чрезвычайно полезной.
источник
type Statuses
живет в типах, не определенных вами? В противном случае я вижу что-то вроде интерфейса с enum, который лучше подходит, верно?Dictionary<enum, additional_metadata>
. Тип Record - отличный способ представить этот шаблон enum + metadata.