타이프 스크립트에서 레코드 유형은 무엇입니까?


182

무엇을 하는가 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 참조

그리고 고급 유형의 페이지는 언급 Record과 함께 제목 매핑 된 형식에서 Readonly, Partial그리고 Pick그 정의로 보이는 년 :

type Record<K extends string, T> = {
    [P in K]: T;
}

읽기 전용, 부분 및 선택은 동형이지만 레코드는 그렇지 않습니다. 레코드가 동형이 아닌 한 가지 단서는 속성을 복사하기 위해 입력 유형을 사용하지 않는다는 것입니다.

type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>

그리고 그게 다야. 위의 인용문 외에도 typescriptlang.orgRecord 에 대한 다른 언급은 없습니다 .

질문

  1. 누군가가 무엇인지에 대한 간단한 정의를 줄 수 있습니까 Record?

  2. 가 Record<K,T>단지 "이 개체의 모든 속성 유형이있을 것이다 말하는 방법 T"? 아마도 모든 속성이 아닙니다. K목적이 있기 때문에 ...

  3. K제네릭이 아닌 객체의 추가 키를 금지 합니까, 아니면 키를 K허용하고 속성이로 변환되지 않았 음을 나타냅니다 T.

  4. 주어진 예를 들면 :

     type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>

정확히 이것과 동일합니까? :

    type ThreeStringProps = {prop1: string, prop2: string, prop3: string}

6
4.에 대한 답은 "예"이므로 다른 질문에 대답해야합니다.
— jcalz

답변:


210
  1. 누군가가 무엇인지에 대한 간단한 정의를 줄 수 있습니까 Record?

A Record<K, T>는 속성 키가 K있고 속성 값이 인 객체 유형입니다 T. 즉 ,와 keyof Record<K, T>동일하며 (기본적으로)와 동일합니다 .KRecord<K, T>[K]T

  1. 가 Record<K,T>단지 "이 개체의 모든 속성 유형이있을 것이다 말하는 방법 T"? 아마도 모든 목적이 아닙니다. K목적이 있기 때문에 ...

참고로, K속성 키를 특정 값으로 제한하는 목적이 있습니다. 가능한 모든 문자열 값 키를 허용하려면과 같은 작업을 수행 할 수 Record<string, T>있지만 관용적 인 방법은 과 같은 색인 서명 것 { [k: string]: T }입니다.

  1. K제네릭이 아닌 객체에서 추가 키를 금지 합니까?K허용하고 속성이로 변환되지 않았 음을 나타냅니다 T.

추가 키를 정확히 "금지"하지는 않습니다. 결국 값은 일반적으로 유형에 명시 적으로 언급되지 않은 속성을 가질 수 있지만 이러한 속성이 존재한다는 것을 인식하지 못합니다.

declare const x: Record<"a", string>;
x.b; // error, Property 'b' does not exist on type 'Record<"a", string>'

그것들을 초과 속성 으로 취급합니다 때로는 거부되는 .

declare function acceptR(x: Record<"a", string>): void;
acceptR({a: "hey", b: "you"}); // error, Object literal may only specify known properties

때로는 받아 들여 지기도합니다.

const y = {a: "hey", b: "you"};
acceptR(y); // okay
  1. 주어진 예를 들면 :

    type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>

    정확히 이것과 동일합니까? :

    type ThreeStringProps = {prop1: string, prop2: string, prop3: string}

예!

희망이 도움이됩니다. 행운을 빕니다!


1
"그것을 수행하는 관용적 방법이 색인 서명을 사용하는 것"인 이유는 무엇입니까? 이 "아이디 오마 틱 방식"에 대한 관련 정보를 찾지 못했습니다.
— legend80s

2
원하는 경우 Record<string, V>의미 를 사용할 수 있습니다 {[x: string]: V}. 나는 아마 이것을 직접했다. 인덱스 시그니처 버전은보다 직접적입니다. 동일한 유형이지만 전자는 인덱스 시그니처로 평가되는 매핑 된 유형의 유형 별칭이며 후자는 인덱스 시그니처입니다. 다른 모든 것이 동일하면 후자를 추천합니다. 마찬가지로 다른 상황에 맞는 강력한 이유가 없다면 Record<"a", string>대신 사용 {a: string}하지 않을 것입니다.
— jcalz

1
" 다른 모든 것은 평등하다. 나는 후자를 추천한다. "왜 그런가? 필자의 사전 타자기 자체는 동의하지만, 전자가 타인의 경우 C # 측에서 오는 사람들에게는 자기 의견이 많을 것이며 JavaScript에서 타자기로는 더 나쁘지 않을 것입니다. 해당 구성에 대한 트랜스 필 레이션 단계를 건너 뛰는 데 관심이 있습니까?
— ruffin

1
내 의견 : 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}인덱스 서명 행동.
— jcalz

논리적으로 유형을 유형에 포함 된 모든 값 집합으로 정의 할 수 있다고 지적하고 싶습니다. 이 해석을 감안할 때 Record <string, V>는 가능한 모든 값을 배치하는 대신 코드를 단순화하는 추상화로 합리적이라고 생각합니다. 유틸리티 유형 문서의 예와 비슷합니다. Record <T, V> 여기서 type T = 'a'| 'b'| '씨'. Record < 'a', string>을 수행하지 마십시오. 동일한 패턴을 따르지 않기 때문에 좋은 카운터 예제가 아닙니다. 또한 다른 예제와 마찬가지로 추상화를 통해 코드를 재사용하거나 단순화하기 위해 추가하지 않습니다.
— 스콧 레너드

68

레코드를 사용하면 Union에서 새 유형을 만들 수 있습니다. Union의 값은 새 유형의 속성으로 사용됩니다.

예를 들어 다음과 같은 Union이 있다고 가정 해보십시오.

type CatNames = "miffy" | "boris" | "mordred";

이제 모든 고양이에 대한 정보가 포함 된 개체를 만들고 싶습니다. CatName Union의 값을 키로 사용하여 새 유형을 만들 수 있습니다.

type CatList = Record<CatNames, {age: number}>

이 CatList를 만족 시키려면 다음과 같은 객체를 만들어야합니다.

const cats:CatList = {
  miffy: { age:99 },
  boris: { age:16 },
  mordred: { age:600 }
}

매우 강력한 유형 안전을 얻습니다.

  • 고양이를 잊어 버리면 오류가 발생합니다.
  • 허용되지 않는 고양이를 추가하면 오류가 발생합니다.
  • 나중에 CatNames를 변경하면 오류가 발생합니다. CatNames는 다른 파일에서 가져 와서 여러 곳에서 사용되기 때문에 특히 유용합니다.

실제 반응 예.

최근에 이것을 사용하여 상태 구성 요소를 만들었습니다. 구성 요소는 상태 소품을 수신 한 후 아이콘을 렌더링합니다. 설명을 위해 여기에서 코드를 상당히 단순화했습니다.

나는 이와 같은 노조를 가졌다.

type Statuses = "failed" | "complete";

이것을 사용하여 다음과 같은 객체를 만들었습니다.

const icons: Record<
  Statuses,
  { iconType: IconTypes; iconColor: IconColors }
> = {
  failed: {
    iconType: "warning",
    iconColor: "red"
  },
  complete: {
    iconType: "check",
    iconColor: "green"
  };

그런 다음 객체에서 소품으로 소품을 구조화하여 렌더링 할 수 있습니다.

const Status = ({status}) => <Icon {...icons[status]} />

상태 연합이 나중에 확장되거나 변경되면 상태 구성 요소가 컴파일되지 않으며 즉시 수정할 수있는 오류가 발생합니다. 이를 통해 앱에 추가 오류 상태를 추가 할 수 있습니다.

실제 앱에는 여러 곳에서 참조되는 수십 가지 오류 상태가 있었으므로이 유형 안전은 매우 유용했습니다.


나는 대부분의 시간 type Statuses이 당신이 정의하지 않은 타이핑에 있다고 가정 합니까? 그렇지 않으면 열거 형이 더 잘 맞는 인터페이스와 같은 것을 볼 수 있습니까?
— Victorio Berra

안녕하세요 @ victorio, 열거 형이 문제를 어떻게 해결할지 잘 모르겠습니다. 키를 놓친 경우 열거 형에 오류가 발생하지 않습니다. 키와 값 사이의 매핑 일뿐입니다.
— superluminary

1
무슨 말인지 알 겠어 C #에서 나오면 영리한 방법이 없습니다. 가장 가까운 것은의 사전입니다 Dictionary<enum, additional_metadata>. 레코드 유형은 해당 열거 형 + 메타 데이터 패턴을 나타내는 좋은 방법입니다.
— Victorio Berra
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.