기본 타입(내장 타입)?
: 타입스크립트가 자체적으로 제공하는 타입

● 원시타입(Primitive Type)
: 하나의 값만 저장하는 타입.
- number 타입 : 양수, 음수, 소수, Infinity(양의 무한대), -Infinity(음의 무한대), NaN 포함.
- string 타입 : " "(큰 따옴표), ' '(작은 따옴표), ` `(백틱, 템플릿 리터럴)
- boolean 타입: true / false
- null 타입
- undefined
- 리터럴 타입: 딱 하나의 값만 포함하는 타입
// 리터럴 타입 예시
let numA: 10 = 10;
// 이렇게 설정하면 이제 numA에는 10 이외의 값을 저장할 수 없게 된다.
★ 타입 주석 (type annotation)
let 이름:string = 'kim';
let num1: number = 123;
이런 식으로 콜론과 함께 변수의 타입을 정의하는 방식 (기본 방식임)
(+) let 이름:string | number = 'kim'; (유니온 타입(union type) - |를 이용하여 다양한 타입이 들어올 수 있게 할 수도 있다.)
개발을 하다 보면 임시로 null 값을 사용하는 경우가 있는데, 이때 사용할 수 있는 옵션이 있다.
// strcitNullChecks(엄격한 null 검사) 옵션을 false로 설정
{
"compilerOptions": {
...
"strictNullChecks": false,
...
}
}
→ strictNullChecks 옵션은 strict 옵션의 하위 옵션이기 때문에, strict 옵션이 켜져 있으면 기본적으로 strictNullChecks 옵션도 켜지고, strict 옵션이 꺼져 있으면 strictNullChecks 옵션도 꺼진다.
● 배열과 튜플
★ 배열의 경우에는
let numArr: number[] = [1, 2, 3];
이런 식으로 타입을 지정. 또는,
let numArr: Array<number> = [1, 2, 3];
이런 식으로도 쓸 수 있음. (제네릭 문법)
다양한 타입 요소를 갖는 배열을 만들려면,
let multiArr: (number | string)[] = [1, "hello"];
이런 식으로 배열 요소의 타입이 stirng이거나 number라고 정의할 수 있다. (유니온 타입)
[TIP] 변수에 마우스 커서를 올려보면, 타입 지정을 어떻게 해야 할지 힌트를 얻을 수 있다.
다차원 배열 타입을 정의하고 싶다면,
let doubleArr : number[][] = [
[1, 2, 3],
[4, 5],
];
이런 식으로 []를 연달아 작성하면 됨.
즉, 위 예시에서는 number 타입의 배열을 저장하는 배열을 의미.
>> 튜플 타입
: 길이와 타입이 고정된 배열 (JS에는 없는 TS의 특수한 타입)
배열의 인덱스별로 정해진 타입이 들어가야 할 때 유용하게 사용할 수 있다.
let tup1: [number, number] = [1, 2];
let tup2: [number, string, boolean] = [1, "hello", true];
type Member = [number, boolean]; 이런 식으로 쓰면(타입 별칭),
let john:Member = [20, true]; 무조건 첫째는 number, 둘째는 boolean 타입이 와야 한다.
※ 튜플 타입도 결국 배열이므로 배열 메서드인 push나 pop등을 사용할 수 있다. 이 경우 길이가 달라지지만, 오류가 나지 않는다. 그러므로 튜플 타입에 배열 메서드를 쓸 때는 각별히 주의해야 한다.
● 객체
★ 객체의 경우,
let user: { id: number, name: string; } = {
id: 1,
name: "홍길동"
};
이런 식으로 각 프로퍼티의 타입을 지정해 주어야 한다. (객체 리터럴 타입)
→ 타입스크립트는 "구조적 타입 시스템(Property Based Type System)"을 가지고 있다. 위와 같이 구조를 기준으로 타입을 정의한다. (cf. C언어나 자바는 "명목적 타입 시스템" 즉, 이름을 기준으로 타입을 지정한다.)
선택적 프로퍼티라면?
let user: { id: number, name?: string; } = {
id: 1,
name: "홍길동"
};
이렇게 ?를 추가하면, 이 값은 옵션. 즉, 있어도 되고 없어도 된다.
읽기 전용 프로퍼티를 만들 수도 있다.
let config: { readonly apiKey: string; } = {
apiKey: "MY API KEY",
}
config.apiKey = "lalala" // 오류 발생
◆ 타입 별칭
→ 타입 정의를 변수처럼 하게 해주는 문법.
타입 지정하는 부분이 너무 길어질 때, 중복 코드를 제거할 때 유용하게 사용할 수 있다.
type 작명 = 타입
→ 작명할 땐 대문자로 시작
// 예시 1
// 타입 별칭
type Name = string | number;
// 사용
let 이름 :Name = 'kim';
// 예시 2
// 타입 별칭
type User = {
id: number;
name: string;
nickname: string;
birth: string;
bio: string;
location: string;
};
// 사용
let user: User = {
id: 1,
name: "홍길동",
nickname: "뿅뿅",
birth: "1999.09.09",
bio: "안녕하세요",
location: "부천시",
};
let user2: User = {
id: 2,
name: "최칠복",
nickname: "seven",
birth: "1990.01.01",
bio: "반갑습니다",
location: "서울시",
};
(참고1) 변수 선언과 마찬가지로, 동일한 스코프에 동일한 이름의 타입 별칭을 선언할 수는 없다. 스코프가 다르다면 가능.
(참고2) 타입 변수는 컴파일 과정에서 사라지게 된다.
◆ 인덱스 시그니처
→ 객체 타입을 좀더 유연하게 정의하도록 도와주는 문법
type CountryCodes = {
[key : string] : string
};
// 이 객체 타입에는 key가 string 타입이고, value도 string 타입인 모든 프로퍼티를 포함할 수 있다는 뜻
// 사용 예시
let countryCodes: CountryCodes = {
Korea: "ko",
UnitedState: "us",
UnitedKingdom: "uk",
// (... 약 100개의 국가)
Brazil : 'bz'
};
※ 인덱스 시그니처 타입은 규칙을 위반하지만 않으면 모든 객체를 허용하므로 빈 객체의 경우에도 오류가 나지 않는다. 이 점을 유의해서 사용할 것.
// 반드시 포함해야 하는 프로퍼티가 있다면,
type CountryNumberCodes = {
[key: string]: number;
Korea: number;
};
// 이런 식으로도 쓸 수 있다.
// 이때 주의할 점은 인덱스 시그니쳐의 value 타입과 직접 추가한 프로퍼티의 value 타입이
// 호환되거나 일치해야 한다는 것이다.
type CountryNumberCodes = {
[key: string]: number;
Korea: string; // 오류!
};
● 열거형 타입 (Enum ; Enumerable Type)
: 여러가지 값들에 각각 이름을 부여해 열거해두고 사용하는 타입 (JS에는 없음.)
// 사용 예시
enum Role {
ADMIN = 0,
USER = 1,
GUEST = 2,
}
const user1 = {
name: "이정환",
role: Role.ADMIN, // 관리자
};
const user2 = {
name: "홍길동",
role: Role.USER, // 회원
};
const user3 = {
name: "아무개",
role: Role.GUEST, // 게스트
};
// 개발을 하다 보면, 회원의 역할을 숫자로 지정하는 경우가 많다.
// 문자열로 지정하면 임의적인 부분이 많아 관리하기가 까다롭기 때문이다.
// 하지만 숫자로 지정하는 경우에도 어떤 숫자가 어떤 역할이었는지 헷갈릴 수 있다.
// 그럴 때 이렇게 enum 타입을 사용하면, 혼동 가능성을 줄일 수 있다.
// 결과적으로 user1.role 에는 0이 user2.role에는 1이 user3.role에는 2가 할당되게 된다.
// 참고로 enum 멤버에 숫자 값을 직접 할당하지 않아도
// 0 부터 1씩 늘어나는 값으로 자동 할당된다.
enum Role {
ADMIN, // 0 할당(자동)
USER, // 1 할당(자동)
GUEST, // 2 할당(자동)
}
// 기본적으로 시작되는 숫자를 0이 아닌 다른 숫자로 바꾸고 싶다면,
// 아래와 같이 시작 위치에 직접 할당해주면 된다.
enum Role {
ADMIN = 10, // 10 할당
USER, // 11 할당(자동)
GUEST, // 12 할당(자동)
}
// 또는 중간부터 할당할 수도 있다.
enum Role {
ADMIN, // 0 할당(자동)
USER = 10, // 10 할당
GUEST, // 11 할당(자동)
}
→ 이렇게 멤버의 값이 모두 숫자인 enum을 숫자형 enum 또는 숫자 열거형 타입이라고 부른다.
>> 문자열 열거형
// 예시
enum Language {
korean = "ko",
english = "en",
}
const user1 = {
name: "이정환",
role: Role.ADMIN, // 0
language: Language.korean, // "ko"
};
const user2 = {
name: "홍길동",
role: Role.USER, // 1
language: Language.english, // "en"
};
※ 잠깐, enum은 어떻게 값처럼 사용할 수 있는 걸까?
→ enum은 컴파일 결과 사라지지 않고 자바스크립트 객체로 변환되기 때문.
// 지금까지 본 예시의 컴파일 결과
var Role;
(function (Role) {
Role[Role["ADMIN"] = 0] = "ADMIN";
Role[Role["USER"] = 1] = "USER";
Role[Role["GUEST"] = 2] = "GUEST";
})(Role || (Role = {}));
var Language;
(function (Language) {
Language["korean"] = "ko";
Language["english"] = "en";
Language["japanese"] = "jp";
})(Language || (Language = {}));
const user1 = {
● Any 타입
: 특정 변수의 타입을 확실히 모를 때 사용할 수 있는 타입. 타입스크립트에서만 제공되는 특별한 타입으로, 타입 검사를 받지 않는다. (치트키!)
※ any 타입을 많이 사용하면 타입스크립트를 쓰는 의미가 없기 때문에 최대한 사용하지 않는 것이 권장된다.
→ 런타임 에러를 발생시킬 수 있음.
● Unknown 타입
: unknown 타입은 any 타입과 비슷하지만 보다 안전한 타입이라고 할 수 있다. 왜냐하면 any 타입과 다르게 unknown 타입의 값은 어떤 타입의 변수에도 저장할 수 없고, 어떤 메서드도 사용할 수 없기 때문이다. 즉, (어떤 타입이든 상관없이) 오직 값을 저장하는 행위만 할 수 있는 타입이다.
(만약 unknown 타입의 값을 활용하고 싶다면, 아래와 같이 '타입 좁히기'를 이용해 특정 값이 특정 타입임을 보장해 주어야 한다.)
let unknownVar: unknown;
unknownVar * 2 // 오류 !
if (typeof unknownVar === "number") {
// 이 조건이 참이된다면 unknownVar는 number 타입으로 볼 수 있음
unknownVar * 2; // 오류 X !
}
※ 그러므로 특정 변수가 당장 어떤 값을 받게 될지 모르는 상황이라면, any 타입보단 unknown 타입을 이용하는 것이 더 안전한 선택이다.
● Void 타입
: 아무런 값도 없음을 의미하는 타입. (참고로 void; 공허)
보통은 아래 예시의 func2 와 같이 아무런 값도 반환하지 않는 함수의 반환값 타입을 정의할 때 사용한다.
function func1(): string {
return "hello";
}
function func2(): void {
console.log("hello");
}
※ 타입스크립트 버전 5.1 이후 아무것도 반환하지 않는 함수의 반환값 타입으로 undefined를 명시해도 문제가 발생하지 않도록 수정됨.
● Never 타입
: 존재하지 않는, 불가능한 타입. 보통 함수가 어떠한 값도 반환할 수 없는 상황일 때 사용한다.
// 무한 루프를 도는 경우
function func3(): never {
while (true) {}
}
// 의도적으로 오류를 발생시키는 경우
function func4(): never {
throw new Error();
}
'└ TypeScript' 카테고리의 다른 글
| 한 입 크기로 잘라먹는 타입스크립트 복습용 정리(1) 개론, 시작하기 (0) | 2023.07.06 |
|---|
댓글