유니온(Union)타입
유니온 타입은 하나의 프로퍼티에 다양한 변수가 올 수 있는 타입을 말합니다.
let args: number | string ;
let arg: 'a' | 'b' | 'c' ;
keyof 키워드
keyof 키워드는 타입 값에 존재하는 모든 프로퍼티의 키값을 union 형태로 리턴 받습니다.
interface Todo {
id: number ;
text: string ;
due: Date;
}
type TodoKeys = keyof Todo;
never 타입
never는 에러가 발생했을 때 프로세스를 중단시키지 않고 무시하는 타입입니다.
any를 제외한 다른 모든 타입의 원시 타입으로 사용 가능합니다.
타입이기는 하지만 실제 never 타입으로 변수를 선언할 수 없고 주로 함수의 리턴 타입으로 에러가 발생할 경우 에러를 무시하고 계속 진행시키는 역할을 합니다.
never 타입은 절대로 발생하지 않는 값의 타입을 나타냅니다. 예를 들어, never는 함수 표현식의 리턴 타입이거나, 항상 예외를 던지는 화살표 함수 표현식이거나, 리턴하지 않는 표현식입니다. 변수는 결코 true가 될 수 없는 어떤 타입의 가드에 의해 좁혀 질 때 타입 never를 획득합니다.
never 타입은 모든 타입의 서브 타입이며, 모든 타입에 assign 가능합니다. 하지만 어떤 타입도 never (never 자체 제외)의 하위 타입이 아니고 assign 할 수 없습니다. 어떤 타입도 ‘never’에 assign되지 않습니다.
function error ( message: string ) : never {
throw new Error ( message) ;
}
function fail ( ) {
return error ( 'Something failed' ) ;
}
function infiniteLoop ( ) : never {
while ( true ) { }
}
Partial
모든 속성이 선택 사항으로 설정된 유형을 구성합니다.
이 유틸리티는 주어진 유형의 모든 하위 집합을 나타내는 유형을 반환합니다.
타입 T의 모든 프로퍼티를 Optional 형태로 바꾸어줍니다.
Partial은 타입은 원시 타입에 해당하는 프토 퍼티 값을 할당할 수도 안 할 수도 있지만 원시 타입에 존재하지 않는 값은 할당할 수 없습니다.
type Partial< T > = { [ P in keyof T ] ? : T [ P ] } ;
interface User {
name: string ;
age: number ;
}
let user1: User = { name: 'harry' , age: 23 } ;
let user2: User = { age: 23 } ;
let user2: Partial< User> = { age: 23 } ;
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' ,
} ) ;
Required
모든 속성이 필수로 설정된 유형으로 구성합니다.
모든 Optional 타입들을 언랩핑합니다.
마이너스 연산자는 옵셔널을 제거해주는 연산자입니다.
partials에서 물음표 연산자만 사용한 것처럼 플러스 연산자를 생략할 수 있습니다.
type Required< T > = {
[ P in keyof T ] - ? : T [ P ] ;
} ;
type MutableRequired< T > = { - readonly [ P in keyof T ] - ? : T [ P ] } ;
type ReadonlyPartial< T > = { + readonly [ P in keyof T ] + ? : T [ P ] } ;
interface Props {
a? : number ;
b? : string ;
}
const obj: Props = { a: 5 } ;
const obj2: Required< Props> = { a: 5 } ;
Readonly
읽기만 가능한 프로퍼티를 선언할 때 사용된다.
생성 된 유형의 속성을 재 할당 할 수 없습니다.
모든 프로퍼티를 값을 참조만 할 수 있도록 바꿉니다.
Partial과 비슷하지만 옵셔널(=?)이 아닌 readonly 키워드를 사용합니다.
type Readonly< T > = { readonly [ P in keyof T ] : T [ P ] } ;
interface Card {
name : string;
price : number;
}
type readOnlyCard = Readonly< Card> ;
let readonlyUser : readOnlyCard = { name : "Sonata" , price : 10000 } ;
readonlyUser. price = 3 ;
interface Todo {
title : string;
}
const todo : Readonly< Todo> = {
title : 'Delete inactive users' ,
} ;
todo. title = 'Hello' ;
Record<K,T>
K타입을 Key값 타입으로, T타입을 밸류 값 타입으로 갖는 타입을 리턴합니다.
타입 K와 T를 받아 타입 K를 프로퍼티 키값으로 하는 타입을 만들 수 있습니다. 주로 K에 유니온 문자열 값을 주어 map 형식의 타입을 만들 수 있고 여러 값들을 원하는 키값에 따라 분류할 때 유용합니다.
type Record< K extends keyof any , T > = {
[ P in K ] : T ;
} ;
export interface Car {
name: string ;
price: number ;
}
const productList: Record< 'SONATA' | 'AVANTE' , Car> = {
SONATA : { name: 'SONATA' , price: 10000 } ,
AVANTE : { name: 'SONATA' , price: 10000 } ,
} ;
const nextProductList: Record< string , Car> = {
SONATA : { name: 'SONATA' , price: 10000 } ,
AVANTE1 : { name: 'SONATA' , price: 10000 } ,
AVANTE2 : { name: 'SONATA' , price: 10000 } ,
AVANTE3 : { name: 'SONATA' , price: 10000 } ,
} ;
type memo = { content: string ; date: string } ;
const FRIENDS_LIST = [ 'harry' , 'jason' , 'dukkey' ] as const ;
type FriendTypeArray = typeof FRIENDS_LIST [ number ] ;
type friendType = Record< FriendTypeArray, memo> ;
Pick<T,K>
T 타입으로부터 K 프로퍼티만 추출합니다.
특성 세트를 선택하여 유형을 구성합니다.
키값 T에 속하는 유니온 타입 K를 받아(= K extends keyof T) 매칭 되는 프로퍼티만 리턴합니다.( = [P in K: T [P])
type Pick< T , K extends keyof T > = {
[ P in K ] : T [ P ] ;
} ;
interface Todo {
title: string ;
description: string ;
completed: boolean ;
}
type TodoPreview = Pick< Todo, 'title' | 'completed' > ;
const todo: TodoPreview = {
title: 'Clean room' ,
completed: false ,
} ;
## Exclude<T,U>
T 타입들중 U타입들과 겹치는 타입을 제외합니다.
타입 T가 타입 U를 상속하거나 동일 타입이라면 무시(never)하고 아닐 경우 타입 값을 리턴합니다. 타입 T 또는 타입 U가 유니온 타입으로 온다면 각각의 교집합이 무시(never)됩니다.
type Exclude< T , U > = T extends U ? never : T ;
type T0 = Exclude< 'a' | 'b' | 'c' , 'a' > ;
type T1 = Exclude< 'a' | 'b' | 'c' , 'a' | 'b' > ;
type T2 = Exclude< string | number | ( ( ) => void ) , Function > ;
T타입에서 U타입과 겹치는 타입만을 가져옵니다.
Exclude와 거의 비슷하지만 T와 never의 위치만 다르기 때문에 교집합을 리턴합니다.
type Extract< T , U > = T extends U ? T : never ;
type T0 = Extract< 'a' | 'b' | 'c' , 'a' | 'f' > ;
type T1 = Extract< string | number | ( ( ) => void ) , Function > ;
Omit<T,K>
특정 인터페이스에서 원하지 않는 속성을 제외하는 타입 입니다.
Pick과는 정반대로 T타입으로부터 K프토퍼티를 제거합니다.
Pick과 Exclude를 한 곳에 넣어놓고 보면 다소 가독성이 떨어져 이해하기 난감할 수 있는데 아래 코드를 보시면 조금 더 쉽게 이해할 수 있습니다.
type Omit< T , K extends keyof T > = Pick< T , Exclude< keyof T , K >> ;
type Car = {
name: string ;
price: number ;
brand: string ;
} ;
type RemainingKeys = Exclude< keyof Car, 'brand' > ;
type NoBrandCard = Pick< Car, RemainingKeys> ;
type Omit< T , K extends keyof T > = Pick< T , Exclude< keyof T , K >> ;
interface Test {
a: string ;
b: number ;
c: boolean ;
}
type OmitA = Omit< Test, 'a' > ;
type OmitAB = Omit< Test, 'a' | 'b' > ;
interface Todo {
title: string ;
description: string ;
completed: boolean ;
}
type TodoPreview = Omit< Todo, 'description' > ;
const todo: TodoPreview = {
title: 'Clean room' ,
completed: false ,
} ;
NonNullable
T타입에서 null or undefinded을 제외하고 리턴합니다.
null 혹은 undefined 타입이거나 상속한다면 무시(never) 아니라면 타입을 리턴합니다.
type NonNullable< T > = T extends null | undefined ? never : T ;
type T0 = NonNullable< string | number | undefined > ;
type T1 = NonNullable< string [ ] | null | undefined > ;
Parameters
함수의 파라미터를 타입으로 리턴합니다.
T는 (…args: any) => any로 선언되어있습니다. 모든 파라미터를 인자로 받고 결괏값으로 모든 값을 리턴하기 때문에 사실상 모든 함수를 상속합니다.
infer 키워드는 타입 스크립트가 엔진이 런타임 상황에서 타입을 추론할 수 있도록 하고 그 값을 P에 할당해줍니다. 파라미터 타입을 infer P로 할당하고 함수의 형태가 참이라면 파라미터를 아니라면 무시(never)합니다.
any와 never 모두 함수를 대신하여 파라미터 타입으로 사용할 수 있기 때문에 에러가 발생하지 않습니다.
type Parameters< T extends ( ... args: any ) => any > = T extends (
... args: infer P
) => any
? P
: never ;
declare function f1 ( arg: { a: number ; b: string } ) : void ;
type T0 = Parameters< ( ) => string > ;
type T1 = Parameters< ( s: string ) => void > ;
type T2 = Parameters<< T > ( arg: T ) => T > ;
type T4 = Parameters< typeof f1> ;
type T5 = Parameters< any > ;
type T6 = Parameters< never > ;
type T7 = Parameters< string > ;
type T8 = Parameters< Function > ;
ConstructorParameters
생성자를 갖는 함수 타입의 생성자 파라미터를 리턴합니다. 함수가 아니라면 never를 리턴합니다.
위의 parameters와 비슷하지만 new키워드를 추가하여 생성자 파라미터로 한정하였습니다.
type ConstructorParameters< T extends new ( ... args: any ) => any > =
T extends new ( ... args: infer P ) => any ? P : never ;
class Person {
private _firstname: string ;
private _lastname: string ;
constructor ( firstname: string , lastname: string ) {
this . _firstname = firstname;
this . _lastname = lastname;
}
}
type constructuinArgsType = ConstructorParameters< typeof Person> ;
let personConstructionArgs: constructuinArgsType = [ 'first' , 'last' ] ;
ReturnType
함수의 리턴타입을 가져옵니다.
parameter와 비슷하지만 타입 추론(infer)을 함수의 결괏값에 할당한 후 리턴합니다.
type ReturnType< T extends ( ... args: any ) => any > = T extends (
... args: any
) => infer R
? R
: any ;
let f1 = ( ) => ( { a: 23 , b: 33 } ) ;
type T0 = ReturnType< ( ) => string > ;
type T1 = ReturnType< ( s: string ) => void > ;
type T2 = ReturnType<< T > ( ) => T > ;
type T3 = ReturnType<< T extends U , U extends number [ ] > ( ) => T > ;
type T4 = ReturnType< typeof f1> ;
InstanceType
생성자로 초기화된 인스턴스 타입을 리턴합니다.
타입 추론(infer)을 인스턴스 값에 할당한 후 리턴하였습니다.
type InstanceType< T extends new ( ... args: any ) => any > = T extends new (
... args: any
) => infer R
? R
: any ;
let funTest = ( ) => ( { a: 23 , b: 33 } ) ;
type T0 = ReturnType< ( ) => string > ;
type T1 = ReturnType< ( s: string ) => void > ;
type T2 = ReturnType<< T > ( ) => T > ;
type T3 = ReturnType<< T extends U , U extends number [ ] > ( ) => T > ;
type T4 = ReturnType< typeof funTest> ;
type T5 = ReturnType< any > ;
type T6 = ReturnType< never > ;