Jisoo.

기술블로그

2. Type


썸네일

Type

타입스크립트 타입에 대해 알아봅시다.


💡 타입

타입스크립트는 자바스크립트를 확장한 타입을 제공합니다.

기본 타입 string, number, boolean, undefined, null, symbol, object 이외에 다음과 같은 타입을 제공합니다.

- any

any는 모든 타입을 할당할 수 있는 타입입니다.

타입스크립트에서 타입 검사를 하지 않길 원할 때 사용합니다.

따라서 기본 자바스크립트처럼 동작합니다.

컴파일 시 noImplicitAny를 사용하면 any로 간주할 때 에러를 발생시킵니다.

1let a : any = 10; 2 3// 자바스크립트처럼 동작 4a = 'string'; 5a.push(1);

- unknown

unknown은 모든 타입을 할당할 수 있다는 점에서 any와 비슷하지만 약간의 차이가 있습니다.

any 타입은 모든 타입에 호환할 수 있으나 unknown의 경우 자기 자신과 any에만 호환할 수 있습니다.

1let a : any = 10; 2let b = 20; 3 4// any 타입은 number에 할당 가능 5b = a; 6 7--------------------------------- 8 9let a : unknown = 10; 10let b = 20; 11 12// unknown 타입은 number에 할당 불가 13b = a; -> Error

- never

never 타입은 반환되지 않는 값 또는 절대 도달할 수 없는 값을 의미합니다.

1function fail() : never { 2 // 에러 발생 시 never 3 throw new Error(); 4} 5 6--------------------------------- 7 8functoin func(x : string | number){ 9 if (typeof x === "string") { 10 //... 11 } else if (typeof x === "number") { 12 //... 13 } else { 14 // 절대 도달할 수 없는 값 15 x; 16 } 17}

- 리터럴 타입

리터럴 타입은 구체적 문자열 또는 숫자로 이루어진 타입입니다.

1let a : "hello" = "hello"; 2 3// "hello" 외의 값을 허용하지 않음 4a = "hi";

리터럴 타입은 유니온 타입과 함께 사용할 경우 가능한 모든 타입의 조합을 제공합니다.

1type EmailLocaleIDs = "welcome_email" | "email_heading"; 2type FooterLocaleIDs = "footer_title" | "footer_sendoff"; 3type AllLocaleIDs = `${EmailLocaleIDs | FooterLocaleIDs}_id`; 4// "welcome_email_id" | "email_heading_id" | "footer_title_id" | "footer_sendoff_id" 5 6type Lang = "en" | "ja" | "pt"; 7type LocaleMessageIDs = `${Lang}_${AllLocaleIDs}`; 8// "en_welcome_email_id" | "en_email_heading_id" | "en_footer_title_id" | "en_footer_sendoff_id" 9// "ja_welcome_email_id" | "ja_email_heading_id" | "ja_footer_title_id" | "ja_footer_sendoff_id" 10// "pt_welcome_email_id" | "pt_email_heading_id" | "pt_footer_title_id" | "pt_footer_sendoff_id"

- 유니온 타입

유니온 타입은 여러 타입을 조합하여 만들 수 있는 새로운 타입입니다.

연산자 |, &를 사용해서 만들 수 있습니다.

1// 문자열, 숫자를 받는 변수 2let a : string | number =10; 3 4a = "asdafd"; 5 6// 특정 문자열을 허용하는 변수 7let signal : "red" | "blue" | "yellow" = "red";

유니온 타입을 사용하여 새로운 타입을 생성할 수 있습니다.

1// 타입의 확장 2type name = { 3 name : string; 4} 5 6type age = { 7 age : number; 8} 9 10// name, age 를 프로퍼티로 받는 타입 11type human = name & age; 12 13let jason : human = { 14 name : "jason", 15 age : 20 16}

유니온 타입 등 여러 가지 타입을 가질 수 있는 변수를 사용할 때는 주의할 점이 존재합니다.

바로 해당 변수가 가질 수 있는 모든 타입에 유효한 메서드만 사용 가능하다는 점입니다.

1function func(id : string | number){ 2 // Property 'toUpperCase' does not exist on type 'string | number'. 3 // Property 'toUpperCase' does not exist on type 'number'. 4 console.log(id.toUpperCase()); -> Error 5}

타입스크립트에서는 Narrowing이라는 기법을 사용하여 어떤 값의 타입을 구체적으로 추론할 수 있습니다.

1function func(id : string | number) { 2 if(typeof id === "string){ 3 // 타입스크립트는 이곳에서 id가 string임을 추론합니다. 4 console.log(id.toUpperCase()); 5 } else { 6 // 이곳의 id 타입은 number로 추론합니다. 7 } 8}

💡 타입 별칭과 인터페이스

타입스크립트에서 타입을 재사용하고 싶을 경우, 타입 별칭 또는 인터페이스를 사용할 수 있습니다.

- type

1// 객체의 프로퍼티 설정 2type Point = { 3 x : number; 4 y : number; 5 // 프로퍼티에 ?를 사용하여 옵셔널 프로퍼티 생성 가능 6 z? : number; 7}; 8 9// x,y 값을 가지는 pt 를 매개변수로 받음 10function printCoord(pt : Point){ 11 console.log(pt.x, pt.y); 12} 13 14------------------------------------- 15 16// 유니온 타입의 별칭 설정 가능 17type ID = string | number;

- interface

인터페이스는 객체를 선언하는 방법을 정의합니다.

1interface Point { 2 x : number; 3 y : number; 4 // 프로퍼티에 ?를 사용하여 옵셔널 프로퍼티 생성 가능 5 z? : number; 6} 7 8// x,y 값을 가지는 pt 를 매개변수로 받음 9function printCoord(pt : Point){ 10 console.log(pt.x, pt.y); 11}

- 타입 별칭 / 인터페이스의 확장

  • 타입 별칭
    • & 키워드를 통해 확장할 수 있습니다.
    • 동일한 이름의 타입별칭을 허용하지 않습니다.
1type Atype = { 2 //... 3} 4 5type Btype = { 6 //... 7} 8 9// 동일한 타입 별칭 허용 X 10type Atype = {} -> Error 11 12// 타입 별칭의 확장 13type Ctype = Atype & Btype
  • interface
    • extends 키워드를 통해 확장할 수 있습니다.
    • 동일한 이름의 인터페이스는 자동으로 합쳐집니다.
1interface Atype { 2 name : string; 3} 4 5// 중복된 이름의 인터페이스는 하나로 합쳐집니다. 6interface Atype { 7 age : number 8} 9 10// 결과는 다음과 같습니다. 11// interface Atype { 12// name : string; 13// age : number; 14// } 15 16// 단, 각 프로퍼티는 호환되는 타입이어야 합니다. 17interface Atype { 18 name : number; -> Error 19} 20 21interface Btype { 22 name : number; 23} 24 25// 호환되지 않는 프로퍼티 간 확장 시 해당 타입은 never 타입입니다. 26type Ctype = AType & BType 27 28// 다음과 같습니다. 29// type Ctype = { 30// name : never; 31// } 32---------------------------------------------------- 33 34// extends 키워드를 통해 확장 가능합니다. 35interface Atype { 36 name : string; 37} 38 39interface Btype extends Atype { 40 // name : string 이 존재합니다. 41 age : number; 42}

- type vs interface

인터페이스와 타입 별칭은 기능적으로 동일하나 몇 가지 차이점이 존재합니다.

  1. 확장 방식
1// type 2type Animal = { 3 name: string 4} 5 6type Bear = Animal & { 7 honey: Boolean 8} 9 10---------------------------------- 11 12// interface 13interface Animal { 14 name: string 15} 16 17interface Bear extends Animal { 18 honey: boolean 19}
  1. 타입의 경우 새 프로퍼티 추가가 불가능, 인터페이스는 자유롭게 가능
1type Window = { 2 title: string 3} 4 5type Window = { 6 ts: TypeScriptAPI 7} -> Error: Duplicate identifier 'Window'. 8 9---------------------------------- 10 11interface Window { 12 title: string 13} 14 15// Window 에 ts 프로퍼티 추가 16interface Window { 17 ts: TypeScriptAPI 18}

💡 배열

- Array

자바스크립트에서 배열은 항상 어떤 값이든 포함 가능한 상태입니다.

타입스크립트에서의 배열은 선언 시 특정 타입의 요소만을 지정할 수 있습니다.

1// javascript 2let list = [1,2,3]; 3 4// 어떤 타입이든 추가할 수 있습니다. 5list.push(true); 6list.push('12'); 7 8------------------------------------ 9 10// typescript 11let list = [1,2,3]; // 생성 시 Array<number> 또는 number[]로 타입 추론 12 13list.push(true); -> Error

또한 타입스크립트는 읽기 전용 배열 ReadonlyArray를 제공합니다.

1let a : ReadonlyArray<string> = [ 'asda', 'dsts', 'zz' ]; 2 3// 조작 불가 4a.push('dadsa); -> Error

ArrayReadonlyArray 타입은 할당할 수 없습니다.

1let x: readonly string[] = []; 2let y: string[] = []; 3 4// ReadonlyArray에 Array 할당 가능 5x = y; 6 7// 반대는 불가능 8y = x; -> Error

- Tuple

튜플은 요소의 개수와 타입이 정확하게 지정된 배열을 의미합니다.

배열 [ ] 내부에 타입을 선언하여 사용할 수 있습니다.

1function func(x : [string, number]) { 2 let a = x[0]; // string 3 let b = x[1]; // number 4}

튜플은 나머지 요소를 가질 수 있으며 배열/튜플 타입이 올 수 있습니다.

1function func(x : [string, number, ...boolean[]){};

readonly를 사용하여 읽기전용 튜플을 만들 수 있습니다.

1function doSomething(pair: readonly [string, number]) { 2 // ... 3}

💡 함수

타입스크립트에서는 함수의 매개변수 타입, 반환 값 타입을 지정할 수 있습니다.

1function func(x : string) : string { 2 return x; 3} 4 5// 아무것도 반환하지 않으면 void 타입 반환 6function func2() : void {}

익명 함수, 화살표 함수가 선언된 곳에서 해당 함수의 매개 변수의 타입을 추론할 수 있습니다.

1const names = ["Alice", "Bob", "Eve"]; 2 3// 타입스크립트는 s를 string으로 추론 4names.forEach((s) => { 5 console.log(s.toUpperCase()); 6}); 7

💡 객체

자바스크립트에서 객체는 프로퍼티를 가지는 값을 의미합니다.

타입스크립트에서 해당 프로퍼티의 타입, 권한 등 여러 가지 설정을 할 수 있습니다.

  • readonly : 객체의 프로퍼티 값을 읽기 전용으로 설정
  • ? : 프로퍼티 뒤에 붙을 경우 해당 값이 필수적이지 않음을 알림
1type human = { 2 name : string, 3 age : number, 4 nickname? : string, // 옵셔널 프로퍼티 5} 6 7const jason = { 8 readonly name : "jason" 9 age : 20, 10 // nickname 은 필수 프로퍼티가 아니기 때문에 생략 가능 11} 12 13// 필수 프로퍼티는 삭제 불가 14delete jason.age; 15 16// const 는 변수의 프로퍼티 값 변경을 막지 않음 17jason.age = 21 18 19// readonly 프로퍼티의 경우에만 프로퍼티 값 변경을 제한 20jason.name = "jack" -> Error

- 객체 고정하기

객체 프로퍼티 전체를 고정할 경우 as const를 사용합니다.

as const로 상수가 된 객체는 하나의 리터럴 타입이 될 수 있습니다

1const human = { 2 name : 'jason', 3 age : 20 4} as const

💡 Enum

Enum은 이름이 있는 상수의 집합입니다.

각 프로퍼티는 값을 가지고 있으며 기본적으로 첫 프로퍼티의 값을 0으로 시작하여 1씩 증가합니다.

1enum Direction { 2 // 프로퍼티의 값을 할당할 수 있습니다. 3 Up = 1, 4 // 이후의 값은 1씩 증가합니다. 5 Down, 6 Left, 7 Right, 8}

Enum은 타입스크립트의 객체에 as const를 한 것과 동일한 기능을 제공합니다.


💡 마무리

타입스크립트의 타입에 대해 알아보았습니다.

다음에는 객체의 타입과 제너릭에 대해 알아보겠습니다.

1. Typescript는 무엇인가
3. 함수 및 객체의 타입과 제너릭

1


Typescript 시리즈의 다른 포스트

썸네일-0

3. 함수 및 객체의 타입과 제너릭

타입스크립트의 함수 및 객체의 타입과 제너릭에 대해서 알아봅시다.


2024년 11월 11일

썸네일-1

1. Typescript는 무엇인가

타입스크립트에 대해서 알아봅시다.


2024년 10월 23일

관련 포스트

썸네일-0

2. 변수와 자료형

식별자와 자료형에 대해서 알아봅시다.


2024년 10월 16일

썸네일-1

1. Javascript 특징

자바스크립트 특징에 대해 알아봅시다.


2024년 10월 16일