ko id ko ko ko ko es en en ko ko ko en ko ko en ko ko ko ko en en ko ko en ko en ko en ko en ko ko ko si en ko en en en
TypeScript 배우기 - 12. 매핑된 타입
TypeScript는 마치 매크로 언어처럼 기존 타입을 기반으로 새로운 타입을 쉽게 만들 수 있습니다.
매핑된 타입은 사전에 선언되지 않은 속성 타입을 선언하는데 사용하는 인덱스 서명 구문을 기반으로 합니다.
아래는 인덱스 서명 구문으로 표현된 예시입니다.
type OnlyBoolsAndHorses = { [key: string]: boolean | Horse; }; const conforms: OnlyBoolsAndHorses = { del: true, rodney: false, };
JavaScript에서 속성은 a["propertyName"]으로 표현될 수 있으므로 [key: string]: boolean | Horse로 표현할 수 있습니다. 그러므로 conforms의 del 및 rodney는 boolean 타입을 반환하므로 정상 코드가 됩니다.
매핑된 타입은 in keyof를 사용해서 제네릭 인자의 타입을 순회하여 동일한 속성을 가진 새로운 타입을 정의합니다.
type OptionsFlags  = { [Property in keyof Type]: boolean; };
다음은 매핑된 타입의 예시입니다.
type FeatureFlags = { darkMode: () => void; newUserProfile: () => void; }; // FeatureFlags의 속성 (함수 포함)을 그대로 받아 반환형을 `boolean`으로 바꿔줌 // type FeatureOptions = { // darMode: boolean; // newUserProfile: boolean; // } type FeatureOptions = OptionsFlags ;
readonly와 ? 앞에 - 또는 +의 접두사를 붙일 수 있습니다. (+ 접두사는 생략 가능)
// Removes 'readonly' attributes from a type's properties type CreateMutable  = { // `-readonly`에 의해 `readonly`가 제거됨 -readonly [Property in keyof Type]: Type[Property]; }; type LockedAccount = { readonly id: string; readonly name: string; }; // type UnlockedAccount = { // id: string; // name: string; // } type UnlockedAccount = CreateMutable ;
// Removes 'optional' attributes from a type's properties type Concrete  = { // `-?`에 의해 `?`가 제거됨 [Property in keyof Type]-?: Type[Property]; }; type MaybeUser = { id: string; name?: string; age?: number; }; // type USer = { // id: string; // name: string; // age: number; // } type User = Concrete ;
TypeScript 4.1 이상부터 as 절을 이용해서 매핑된 타입의 키를 다시 매핑할 수 있습니다.
type MappedTypeWithNewProperties  = { [Properties in keyof Type as NewKeyType]: Type[Properties] }
다음은 템플릿 리터럴 타입과 결합해서 이전 속성에서 새로운 속성 이름을 만드는 예제 코드입니다.
type Getters  = { [Property in keyof Type as `get${Capitalize }`]: () => Type[Property] }; interface Person { name: string; age: number; location: string; } // type LazyPerson = { // getName: () => string; // getAge: () => number; // getLocation: () => string; // } type LazyPerson = Getters ;
조건부 타입을 통해 never를 생성해서 키를 필터릴 할 수도 있습니다.
// Remove the 'kind' property type RemoveKindField  = { [Property in keyof Type as Exclude ]: Type[Property] }; interface Circle { kind: "circle"; radius: number; } // type KindlessCircle = { // radius: number; // } type KindlessCircle = RemoveKindField ;
string | number | symbol 유니온 타입 뿐만 아니라 다른 유니온 타입에 대해 임의의 매핑을 할 수 있습니다.
type EventConfig  = { [E in Events as E["kind"]]: (event: E) => void; } type SquareEvent = { kind: "square", x: number, y: number }; type CircleEvent = { kind: "circle", radius: number }; // type Config = { // square: (event: SquareEvent) => void; // circle: (event: CircleEvent) => void; // } type Config = EventConfig
대단하군요. 매크로 언어와 같은 느낌입니다.
매핑된 타입은 다른 조작 섹션의 기능과 잘 결합하여 작동합니다. 다음은 pii 속성이 리터럴 true로 설정되어 있는지의 유무에 따라 true 또는 false를 반환하는 조건부 타입을 사용하는 매핑된 타입의 예시입니다.
type ExtractPII  = { // Type의 키를 순회하며 // `{ pii: true }`가 있는 경우 true, 없는 경우 false 타입이 됨 [Property in keyof Type]: Type[Property] extends { pii: true } ? true : false; }; type DBFields = { id: { format: "incrementing" }; name: { type: string; pii: true }; }; // type ObjectsNeedingGDPRDeletion = { // id: false; // name: true; // } type ObjectsNeedingGDPRDeletion = ExtractPII ;
Powered by Hashnode - a blogging community with over 2 Million members