-
[TS] Utility Typesprograming/Language 2020. 3. 18. 15:40
안녕하세요, Einere입니다.
(ADblock을 꺼주시면 감사하겠습니다.)
이번 포스트에서는 Type Script의 Utility Types에 대해 알아보도록 하겠습니다.
Utility Types
타입스크립트에서는 타입 변환을 용이하게 하기 위해 몇가지 유틸리티 타입을 제공합니다. 이 유틸리티 타입은 전역으로 사용할 수 있습니다.
해당 포스트에서 T는 타입, K는 키(속성), U는 유니온 타입을 의미합니다.
Patial<T>
T의 모든 속성이 선택 사항인 타입을 만들어줍니다. 즉, T의 모든 하위집합을 나타내는 타입을 반환합니다.
interface Todo { title: string; description: string; } function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) { return { ...todo, ...fieldsToUpdate }; } const todo1 = { title: 'organize desk', description: 'clear clutter', }; const todo2 = updateTodo(todo1, { description: 'throw out trash', });
Readonly<T>
T의 모든 속성이 읽기전용인 타입을 만들어줍니다. 즉, 이 타입을 가진 변수는 재할당이 불가능합니다.
interface Todo { title: string; } const todo: Readonly<Todo> = { title: 'Delete inactive users', }; todo.title = 'Hello'; // Error: cannot reassign a readonly property
Record<K, T>
T를 타입으로 가지는 K의 속성들의 집합을 만들어줍니다. 이 유틸리티 타입은 특정 타입의 속성을 또다른 타입의 속성들에 매핑하는데 유용합니다.
interface PageInfo { title: string; } type Page = 'home' | 'about' | 'contact'; const x: Record<Page, PageInfo> = { about: { title: 'about' }, contact: { title: 'contact' }, home: { title: 'home' }, };
Pick<T, K>
T에서 K만 추출한 타입을 만들어줍니다.
interface Todo { title: string; description: string; completed: boolean; } type TodoPreview = Pick<Todo, 'title' | 'completed'>; const todo: TodoPreview = { title: 'Clean room', completed: false, };
Omit<T, K>
T에서 모든 속성을 고른 후, K를 제거한 타입을 만들어줍니다.
interface Todo { title: string; description: string; completed: boolean; } type TodoPreview = Omit<Todo, 'description'>; const todo: TodoPreview = { title: 'Clean room', completed: false, };
Exclude<T, U>
U에 할당가능한 모든 속성을 T에서 제거한 타입을 만들어줍니다.
type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c" type T1 = Exclude<"a" | "b" | "c", "a" | "b">; // "c" type T2 = Exclude<string | number | (() => void), Function>; // string | number
Extract<T, U>
U에 할당가능한 모든 속성을 T에서 추출한 타입을 만들어줍니다.
type T0 = Extract<"a" | "b" | "c", "a" | "f">; // "a" type T1 = Extract<string | number | (() => void), Function>; // () => void
NonNullable<T>
T에서
null
과undefined
를 제거한 타입을 만들어줍니다.type T0 = NonNullable<string | number | undefined>; // string | number type T1 = NonNullable<string[] | null | undefined>; // string[]
Parameters<T>
함수 T의 파라미터들의 타입을 튜플 타입으로 만들어줍니다.
declare function f1(arg: { a: number, b: string }): void type T0 = Parameters<() => string>; // [] type T1 = Parameters<(s: string) => void>; // [string] type T2 = Parameters<(<T>(arg: T) => T)>; // [unknown] type T4 = Parameters<typeof f1>; // [{ a: number, b: string }] type T5 = Parameters<any>; // unknown[] type T6 = Parameters<never>; // never type T7 = Parameters<string>; // Error type T8 = Parameters<Function>; // Error
ConstructorParameters<T>
생성자 함수 T의 파라미터들의 타입을 추출한 타입을 만들어줍니다.
type T0 = ConstructorParameters<ErrorConstructor>; // [(string | undefined)?] type T1 = ConstructorParameters<FunctionConstructor>; // string[] type T2 = ConstructorParameters<RegExpConstructor>; // [string, (string | undefined)?]
ReturnType<T>
함수 T의 반환 값의 타입을 만들어줍니다.
declare function f1(): { a: number, b: string } type T0 = ReturnType<() => string>; // string type T1 = ReturnType<(s: string) => void>; // void type T2 = ReturnType<(<T>() => T)>; // {} type T3 = ReturnType<(<T extends U, U extends number[]>() => T)>; // number[] type T4 = ReturnType<typeof f1>; // { a: number, b: string } type T5 = ReturnType<any>; // any type T6 = ReturnType<never>; // any type T7 = ReturnType<string>; // Error type T8 = ReturnType<Function>; // Error
InstanceType<T>
생성자 함수 T로 생성된 인스턴스의 타입을 만들어줍니다.
class C { x = 0; y = 0; } type T0 = InstanceType<typeof C>; // C type T1 = InstanceType<any>; // any type T2 = InstanceType<never>; // any type T3 = InstanceType<string>; // Error type T4 = InstanceType<Function>; // Error
Required<T>
타입 T의 모든 속성을 필수로 만든 타입을 만들어줍니다.
interface Props { a?: number; b?: string; }; const obj1: Props = { a: 5 }; // OK const obj2: Required<Props> = { a: 5 }; // Error: property 'b' missing
ThisParameterType<T>
함수 T의
this
파라미터의 타입을 추출합니다. 만약this
파라미터가 없다면unknown
이 됩니다.단, 해당 유틸리티 타입은
--strictFunctionTypes
이 enable일 때 정상적으로 작동합니다.function toHex(this: Number) { return this.toString(16); } function numberToString(n: ThisParameterType<typeof toHex>) { return toHex.apply(n); }
OmitThisParameter<T>
함수 T에서
this
파라미터를 제거합니다.단, 해당 유틸리티 타입은
--strictFunctionTypes
이 enable일 때 정상적으로 작동합니다.function toHex(this: Number) { return this.toString(16); } // The return type of `bind` is already using `OmitThisParameter`, this is just for demonstration. const fiveToHex: OmitThisParameter<typeof toHex> = toHex.bind(5); console.log(fiveToHex());
ThisType<T>
해당 유틸리티 타입은 변환된 타입을 반환하지는 않습니다. 대신, 문맥적
this
타입을 위한 마커로서 사용됩니다.해당 유틸리티 타입은
--noImplicitThis
가 enable이어야 사용할 수 있습니다.type ObjectDescriptor<D, M> = { data?: D; methods?: M & ThisType<D & M>; // Type of 'this' in methods is D & M } function makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & M { let data: object = desc.data || {}; let methods: object = desc.methods || {}; return { ...data, ...methods } as D & M; } let obj = makeObject({ data: { x: 0, y: 0 }, methods: { moveBy(dx: number, dy: number) { this.x += dx; // Strongly typed this this.y += dy; // Strongly typed this } } }); obj.x = 10; obj.y = 20; obj.moveBy(5, 5);
많이 복잡하지만, 핵심은
moveBy
함수 내부에서 사용되는this
의 타입은 D & M이 된다는 것입니다.만약 JS의 경우라면
moveBy
내부의 this는methods
를 가리키게 되겠죠.참고
https://www.typescriptlang.org/docs/handbook/utility-types.html
'programing > Language' 카테고리의 다른 글
[TS, React] styled-component에 ref 사용하기 (0) 2020.04.17 [TS] 깊은 복사(deep copy) 라이브러리 (0) 2020.03.30 [TS] TS with React - hook 사용하기 3 (0) 2020.02.23 [TS] TS with React - hook 사용하기 2 (0) 2020.02.23 [TS] TS with React - hook 사용하기 1 (0) 2020.02.23 댓글