[TS] (3) 기초 : 기본 타입
저번 벨로그에서 타입 선언과 타입 추론에 대해서 알아보았다
[TS] (2) 기초 : 타입 선언과 타입 추론
이제는 타입을 적을 위치에 들어갈 기본적인 타입들에 대해서 공부해보자!!// 여기 들어갈 타입? someVariable: ?????;
1. 자바스크립트와 동일한 타입
1) 원시 타입(Number,String,Boolean,Null, Undefined)
- 타입 선언 : 소문자로 작성(number, string, boolean, null, undefined)
- 타입 추론 : 변수 선언'만' 할 때(let 키워드, 기본값이 없는 매개변수)를 제외하고는 할당된 값의 타입이 '원시 타입'일 경우에 타입을 선언할 필요는 없습니다.
// 예시
let unde: undefined;
let e:null;
const obj = {
key: "hello", // 프로퍼티의 값의 타입으로 추론됨
};
const fun4 = (a=1, b:string)=> { // 기본 값이 있고 그 값이 원시 타입인 경우 타입 선언 생략 가능
console.log(a)
console.log(b)
}
fun4(2,"hello")
2) 객체 타입(참조 타입)
- 특징
- 원시 타입이 아닌 모든 타입이 객체 타입(참조 타입)이며, 객체, 배열, 함수도 이에 해당한다.
- 여러 타입들로 객체 타입이 선언될 수 있다.
- 타입 선언 : 중괄호로 선언하며, key:type 쌍으로 객체 내부 프로퍼티의 타입을 정한다.
- 각 쌍은 콤마(,)가 아니라 세미콜론(;)으로 구분한다.
- 중첩이 가능하다(Nested Objects).
- 타입 추론 : 각 프로퍼티의 타입이 모두 추론 가능하면 객체 타입의 선언 자체룰 생략할 수 있지만, 명시적인 선언이 하나라도 필요하다면 모든 타입에 대해 작성해주어야 한다.
const objDeep = {
key1: "sdfsdf",
key2: {
name: "kim",
job: "developer",
},
isMale: true,
};
// 객체(타입 선언 필요함) : arr 대응하는 프로퍼티의 타입이 tuple(길이 고정, 각 인덱스의 타입 정해짐)이었으면 좋겠다. 이 때는 타입을 모두 선언해주어야 함.
// 타입 선언을 하지 않으면 arr 프로퍼티의 타입이 유니온 타입(추후 설명)으로 결정됨(x)
const typeNeeded: {
key1: string;
key2: {
name: string;
job: string;
};
arr: [number, boolean, string];
} = {
key1: "sdfsdf",
key2: {
name: "kim",
job: "developer",
},
arr: [2, true, "hello"],
};
우리가 원하는 arr의 타입이 tuple(길이가 고정, 각 인덱스 타입 고정인 배열) 이라면 선언 필요(이후 설명)
- 타입 선언했을 때 arr(tuple 타입)
- 타입을 선언하지 않았을 때 arr(union 타입)
2. 타입스크립트에 추가된 타입
알아야 할 것 : 배열 관련 타입은 원래 자바스크립트에서는 객체 타입에 포함되었으나, 타입스크립트에서는 명시적으로 다른 타입으로써 선언 가능하다. (물론 자바스크립트로 컴파일되면 객체 타입이다 ㅎㅎ)
1) 배열 타입(참조 타입)
- 타입 특징
- 길이가 고정되지 않았으며, 배열 항목에 들어갈 수 있는 타입을 결정한다.
- 객체 타입과 마찬가지로, 여러 타입들로 배열 타입이 구성될 수 있다.
- 항목의 타입에는 어떤 타입이던 다 들어갈 수 있기 때문에 타입이 확장된 TS에서는 더욱 다채로운 배열 타입을 선언할 수 있다.
- 타입 선언 : '포함된(될) 항목 타입[]'
// 배열 타입 선언하기(추론 없이)
const arr1: string[] = ["Hello","Bye"]; // string으로만 이루어진 배열 타입
const arr2: (string | number)[] = ["Hello",12]; // string이나 number 타입만 가능(union 타입 포함됨. 이후 다룰 것!)
let arr3: string[];
- 타입 추론 : 변수 선언'만' 할 때(let 키워드, 기본값이 없는 매개변수)를 제외하고는 할당된 값의 타입이 '배열 타입'일 경우에 타입을 선언할 필요는 없다. 위 코드 3개의 배열와 각각 비교해보자.
const arr1 = ["Hello","Bye"]; // 사실 위처럼 타입 선언할 필요 없다. 아래 이미지 참고
// 예시
let unde: undefined;
let e:null;
const obj = {
key: "hello", // 프로퍼티의 값의 타입으로 추론됨
};
const fun4 = (a=1, b:string)=> { // 기본 값이 있고 그 값이 원시 타입인 경우 타입 선언 생략 가능
console.log(a)
console.log(b)
}
fun4(2,"hello")
- 원시 타입이 아닌 모든 타입이 객체 타입(참조 타입)이며, 객체, 배열, 함수도 이에 해당한다.
- 여러 타입들로 객체 타입이 선언될 수 있다.
- 각 쌍은 콤마(,)가 아니라 세미콜론(;)으로 구분한다.
- 중첩이 가능하다(Nested Objects).
const objDeep = {
key1: "sdfsdf",
key2: {
name: "kim",
job: "developer",
},
isMale: true,
};
// 객체(타입 선언 필요함) : arr 대응하는 프로퍼티의 타입이 tuple(길이 고정, 각 인덱스의 타입 정해짐)이었으면 좋겠다. 이 때는 타입을 모두 선언해주어야 함.
// 타입 선언을 하지 않으면 arr 프로퍼티의 타입이 유니온 타입(추후 설명)으로 결정됨(x)
const typeNeeded: {
key1: string;
key2: {
name: string;
job: string;
};
arr: [number, boolean, string];
} = {
key1: "sdfsdf",
key2: {
name: "kim",
job: "developer",
},
arr: [2, true, "hello"],
};
우리가 원하는 arr의 타입이 tuple(길이가 고정, 각 인덱스 타입 고정인 배열) 이라면 선언 필요(이후 설명)
- 타입 선언했을 때 arr(tuple 타입)
- 타입을 선언하지 않았을 때 arr(union 타입)
알아야 할 것 : 배열 관련 타입은 원래 자바스크립트에서는 객체 타입에 포함되었으나, 타입스크립트에서는 명시적으로 다른 타입으로써 선언 가능하다. (물론 자바스크립트로 컴파일되면 객체 타입이다 ㅎㅎ)
1) 배열 타입(참조 타입)
- 타입 특징
- 길이가 고정되지 않았으며, 배열 항목에 들어갈 수 있는 타입을 결정한다.
- 객체 타입과 마찬가지로, 여러 타입들로 배열 타입이 구성될 수 있다.
- 항목의 타입에는 어떤 타입이던 다 들어갈 수 있기 때문에 타입이 확장된 TS에서는 더욱 다채로운 배열 타입을 선언할 수 있다.
- 타입 선언 : '포함된(될) 항목 타입[]'
// 배열 타입 선언하기(추론 없이)
const arr1: string[] = ["Hello","Bye"]; // string으로만 이루어진 배열 타입
const arr2: (string | number)[] = ["Hello",12]; // string이나 number 타입만 가능(union 타입 포함됨. 이후 다룰 것!)
let arr3: string[];
- 타입 추론 : 변수 선언'만' 할 때(let 키워드, 기본값이 없는 매개변수)를 제외하고는 할당된 값의 타입이 '배열 타입'일 경우에 타입을 선언할 필요는 없다. 위 코드 3개의 배열와 각각 비교해보자.
const arr1 = ["Hello","Bye"]; // 사실 위처럼 타입 선언할 필요 없다. 아래 이미지 참고
const arr2 = ["Hello", 12]; // string이나 number 타입 항목이 들어간 배열을 원한다면
// 여기도 마찬가지로 선언할 필요 없다. 아래 이미지 참고
let arr2: string[]; // 변수 선언만 할 때는 타입 선언을 해줘야 함
2) tuple 타입 : 길이가 고정된 배열
- 타입 특징
- 배열 내 항목에 들어갈 타입이 각 인덱스마다 정해져 있고, 배열의 길이가 고정됨
- 여러 타입들로 tuple 타입이 구성될 수 있다.
- 타입 선언 : [타입,타입,타입,...]
// Good
const arr4: [number, string, () => number] = [
12,
"Hi",
() => {
return 3;
},
]; // 배열의 길이가 3이고, 배열 내 항목의 타입이 인덱스 순서대로 number, string, number를 return하는 함수(이후 설명 예정)
- 타입 추론(거의 불가) : 할당된 값에 의한 타입 추론에 의지하면, 유니온(union) 타입이 되므로 웬만하면 명시적인 선언이 필요할 것이다.
// 위 코드에서 타입 선언을 제외하면 그저 number 혹은 string 혹은 function 타입을 가지는 유니온 타입의 배열이 되어버린다.
// Bad
const arr4 = [
12,
"Hi",
() => {
return 3;
},
];
// 아래 이미지 참고!
- 주의!!! : 길이 고정을 벗어나는 예외는 있다 -> 길이에 영향을 주는 자바스크립트 array 빌트인 메서드(push, pop 등등)
이런 메서드를 안쓰는 것도 좋으나, 아예 이런 걸 막고 싶다면 좀 더 복잡한 타입 선언이 필요할 듯 하다.
아직 나는 초보라서 다음에 알아보자. ㅠㅠ
[stackoverflow] tuple에 적용되는 메서드에 대한 질문
3) any 타입 : 타입 검사를 하지 않는 타입
-
타입 특징
- 가장 자바스크립트처럼 사용할 수 있는 타입이며, 잘못 사용하면 타입스크립트를 사용하는 의미가 희석될 수 있다.
- 모든 타입을 할당받을 수 있다.
- 타입 검사가 필요한 모든 과정을 지나친다. 웬만하면 unknown 타입을 사용하자. -
타입 선언 : any
let anyType: any; // any 타입
let b: any[] = [] // any[] 타입
console.log(anyType.push("Hello")); // 컴파일 에러가 발생하지 않음. 런타임 에러 예상됨..
- 타입 추론 : 변수를 선언할 때 아무 값도 할당하지 않으면(let 키워드 혹은 기본값 없는 매개변수 등) any 타입으로 추론된다.
let a; // any 타입 추론
// 'a' 변수는 암시적으로 'any' 형식이지만, 사용량에서 더 나은 형식을 유추할 수 있습니다.
let b = [] // any[] 타입 추론
4) unknown 타입 : 어떤 타입이든 허용하지만 타입 체크
- 타입 특징
- any와 유사하지만 타입 검사를 거친다. 즉 어떤 타입이든 할당할 수 있지만 할당한 변수를 사용할 때 타입 체크를 해줘야 할 의무가 있다.
- 모든 타입의 최상위에 있다. any 타입 포함
- 타입 선언 : unknown
- 타입 추론 : 불가
- 타입 체크 예시 : 아래 참조
let unknownType: unknown;
unknownType = 12;
let unknownArray: unknown = ["dfd"];
console.log(unknownType.push("Hello")); // 에러 발생
let unknownType: unknown;
unknownType = 12;
let unknownArray: unknown = ["dfd"];
if (Array.isArray(unknownType)) {
console.log(unknownType.push("Hello")); // 에러 없음!
}
5) union 타입 : 특정 타입만 허용하고 싶을 때
-
타입 특징 : 두 개 이상의 타입을 할당할 수 있다. 'or'으로 이해하면 편하다.
-
타입 선언 : 타입 | 타입 | 타입 ...
let stringOrNumber: string | number;
- 타입 추론 : 할당되는 값이 여러 타입을 항목으로 가진 배열 혹은 논리합 연산자(||)로 이루어진 표현식일 때 추론이 가능하다.
let c = "sdf" || 12 // c: string | number 추론
c = true // 'boolean' 형식은 'string | number' 형식에 할당할 수 없습니다.
const arr5 = [12, "sdf"] // arr5: (number | string)[] 추론 <- 위에서 많이 봤죠?
6) (문자열) 리터럴 타입 : 유니크한 특정 상수만 허용하고 싶을 때
-
타입 특징
- 문자열 리터럴 자체를 타입으로 지정하여, 해당 변수가 그 타입의 값만 가질 수 있도록 제한하는 유니크한 타입이다.
- 보통 union 타입과 같이 사용하여 특정 상수만 허용하고 싶을 떄 선언한다. -
타입 선언: 문자열 리터럴
let d: "frontend"| "backend";
d = "I love you" // '"I love you"' 형식은 '"frontend" | "backend"' 형식에 할당할 수 없습니다.
- 타입 추론: 불가
IDE(나의 경우 vscode)의 지원 : (큰 / 작은) 따옴표 입력 시
7) enum 타입 : 같은 종류의 열거형 상수들을 가독성 있게
- 타입 특징
- 같은 ‘종류’를 나타내는 여러 개의 숫자 혹은 문자열을 다뤄야 하는데, 각각 적당한 이름을 붙여서 코드의 가독성을 높이고 싶다면 enum을 사용한다. (사실 나는 enum 타입이 제일 어색하다..)
- 객체 타입이지만, 초기화 후 객체 내 프로퍼티를 바꿀 수 없다.
- 프로퍼티가 숫자 열거형(0부터)으로 자동 결정되며, 필요에 따라 선언할 때 이를 초기화하여 변경할 수 있다.
- tree-shaking(사용되지 않는 코드 덜어내기)이 안되어 사용을 권하지 않는다고도 하니 주의하자. 아래 링크 참고!더 자세한 설명은 다른 분이 올려주신 좋은 글이 있다.
TypeScript enum을 사용하는 이유
이론
Handbook - Enums - TypeScript
enum과 tree-shaking 관한 글
TypeScript enum을 사용하지 않는 게 좋은 이유를 Tree-shaking 관점에서 소개합니다. - 타입 선언 : enum 타입명 { EXAMPLE, HI, ... } (관습상 대문자로 선언합니다)
// 숫자 열거형 : 초기화 안함(기본 0부터)
enum WebDeveloper {
FRONTEND,
BACKEND,
}
console.log(WebDeveloper.FRONTEND) // 0
console.log(WebDeveloper.BACKEND) // 1
// 숫자 열거형 : 초기화 (초기화한 다음 인덱스부터 차례로 1씩 증가. 전 인덱스에는 영향 없음)
enum Browser {
CHROME,
SAFARI,
WHALE = 10,
BRAVE,
}
console.log(Browser.CHROME) // 0
console.log(Browser.SAFARI) // 1
console.log(Browser.WHALE) // 10
console.log(Browser.BRAVE) // 11
// 문자열 열거형 : 초기화 (문자열 초기화된 이후 항목들은 초기화해야 함). 유의미한 정보 전달
enum Browser {
CHROME = "ch",
SAFARI = "sa",
WHALE = "wh",
BRAVE = "br",
}
console.log(Browser.CHROME) // "ch"
console.log(Browser.SAFARI) // "sa"
console.log(Browser.WHALE) // "wh"
console.log(Browser.BRAVE) // "br"
// 이종 열거형 : 여러 개의 타입으로 초기화(굳이 사용할 필요 없음)
enum Browser {
CHROME = "ch",
SAFARI = 10,
WHALE,
BRAVE ,
}
console.log(Browser.CHROME); // "ch"
console.log(Browser.SAFARI); // 10
console.log(Browser.WHALE); // 11
console.log(Browser.BRAVE); // 12
- 타입 추론 : 불가
8) (함수의 return)void 타입 : 함수가 return 하지 않음
- 타입 특징
- 함수의 return 값의 타입을 선언할 때 활용되는 타입 중 하나이다.
- 함수가 return하지 않을 때(return문이 없을 때) return 값의 타입을 void로 선언한다.
- void 타입의 함수의 return 값을 출력하면 undefined가 출력된다.(void > undefined, null)
- 변수에도 선언할 수 있지만 void 타입은 null이나 undefined만을 할당할 수 있으므로 그다지 유용하지 않다.
- undefined와는 다름 : return문이 있음(함수에서는 드물게 쓰임)
// 함수의 return값 타입을 undefined로 하려면 const undefinedFunc = (): undefined => { return; }
- 타입 선언 : void
// void
const voidFunc = (): void => {
console.log("Hello");
};
console.log(voidFunc) // undefined
- 타입 추론 : 함수 선언 시 함수의 return문이 없을 경우 void 타입으로 추론된다. 위 코드에서 ": void"를 삭제하더라도 추론이 잘 된다.
// void
const voidFunc = () => {
console.log("Hello");
};
console.log(voidFunc) // undefined
9) (함수의 return) never 타입 : 절대로 발생하지 않는 값의 타입
- 타입 특징
- 함수의 return 값의 타입을 선언할 때 활용되는 타입 중 하나이다.
- 모든 타입의 assign 될 수 있다. 즉 최하위 타입!
- 절대로 발생하지 않는 값의 타입일 경우 never 타입으로 선언한다.
- '절대로 발생하지 않는 값'이란 뭘까? : 강의에 따르면 함수가 실행되는 순간 script가 cancel/crush/destroy되는 경우(에러, 무한루프 등)를 말한다. - 타입 선언 : never
// never
const neverFunc = (): never => {
throw { message: "에러입니다", errorCode: 500 }; // error 발생
};
const infiniteFunc = (): never => {
while (true) {} // 무한 루프
};
const returnErrorFunc = (): never => {
return neverFunc(); // never값을 return하는 함수
};
- 타입 추론 : 절대로 발생하지 않는 값의 경우나 never 타입을 return하는 경우에 타입이 추론된다. 위 코드의 return 타입 선언은 사실 필요가 없다!
// never 타입 추론
const neverFunc = () => {
throw { message: "에러입니다", errorCode: 500 };
};
const infiniteFunc = () => {
while (true) {}
};
const returnErrorFunc = () => {
return neverFunc();
};
10) 함수 타입 : 함수의 형태를 정하기
- 타입 특징
- 함수 자체를 타입으로 볼 수 있다.
- 함수 내부의 형태 (매개변수의 수와 타입, return 값의 타입)를 선언한다. - 타입 선언 : (매개변수: 타입, 매개변수: 매개변수, ....) => 타입
let getFunc: () => number;
// 매개변수는 없고, return 값이 number 타입인 함수 타입
let getFunc2: (a: number, b: number) => string;
// 2개의 number 타입 매개변수를 가지고, return 값이 string 타입인 함수 타입
- 타입 추론(함수 선언 시) : 매개변수(유무, 개수, 타입)는 추론 불가. return 타입은 코드 문맥에 따라 추론이 가능하다.
let funcType2 = (a: number, b: string) => {
return a.toString() + b;
};
// return 타입은 선언하지 않았으나 return 값이 string인 것이 명확하므로 string 타입으로 추론된다.
3. 다음에 공부할 것
TypeScript Compiler에 대해서...
Author And Source
이 문제에 관하여([TS] (3) 기초 : 기본 타입), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@kimyoungyin/TS-3-기초-기본-타입저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)