# 시작
<실전 리액트 프로그래밍>에 있는 내용을 따라 타입스크립트를 공부해본다. 타입스크립트를 실행하는 환경은 아래 사이트에서 도움을 받았다. 기존에는 컴파일하고 실행하는 귀찮은 과정을 반복했는데 이 방식대로 하면 매우 간편해진다.
방법
ts-node를 설치한다.
npm install -g typescript아래 명령어로 실행한다.
ts-node [해당ts파일이름].ts결과

# 실습
// 93.tsconst size: number = 123;
const isBig: boolean = size >= 100;
const msg: string = isBig ? "크다" : "작다";
// @ : 1) 배열은 두 가지로 정의할 수 있다.const values: number[] = [1, 2, 3];
const values2: Array<number> = [1, 2, 3];
values.push('a');// @ : 타입 에러 2) 숫자 배열에 문자열로 입력하면 타입 에러// @ : 3) 문자열과 숫자로 구성된 튜플 타입 정의const data: [string, number] = [msg, size];
data[0].substr(1);
data[1].substr(1);// @ : 타입 에러 4) 두 번째 아이템의 타입은 숫자인데 문자열의 메서드를 호출하면 타입 에러1) 배열은 두 가지로 정의할 수 있다.
2) 숫자 배열에 문자열로 입력하면 타입 에러
3) 문자열과 숫자로 구성된 튜플 타입 정의
4) 두 번째 아이템의 타입은 숫자인데 문자열의 메서드를 호출하면 타입 에러
null과 undefined
// 94.ts// @ : 1) undefined와 null은 타입으로 사용될 수 있다.let v1: undefined = undefined;
let v2: null = null;
v1 = 123;// @ : 타입 에러 2) undefined 타입에 숫자를 입력하면 타입 에러// @ : 3) undefined와 null 타입은 다른 타입과 함께 유니온 타입으로 정의할 때 많이 사용let v3: number | undefined = undefined;
v3 = 123;
1) undefined와 null은 타입으로 사용될 수 있다.
2) undefined 타입에 숫자를 입력하면 타입 에러
3) undefined와 null 타입은 다른 타입과 함께 유니온 타입으로 정의할 때 많이 사용
문자열 리터럴과 숫자 리터럴 타입
// 95.tslet v1: 10 | 20 | 30;// @ : 1)
v1 = 10;
v1 = 15;// @ : 타입 에러 2)let v2: '경찰관' | '소방관';// @ : 3)
v2 = '의사';// @ : 타입 에러1) 숫자 10, 20, 30은 각각 타입으로 사용했다.2) 나머지 숫자는 입력될 수 없다.
3) 변수 v2를 문자열 리터럴 타입으로 정의했다.
any
// 96.tslet value: any;
value = 123;
value = "456";
value = () => {};
any 는 숫자, 문자열, 함수도 입력 가능하다. 실제로 타입을 알 수 없거나 타입 정의가 안된 외부 패키지를 사용할 때 유용하다.
void와 never
// 97.ts// @ : 1) 아무 값도 반환하지 않음 voidfunction f1(): void {
console.log("hello");
}
// @ : 2) 함수가 비정상적으로 종료되므로 neverfunction f2(): never {
throw new Error("some error");
}
// @ : 3) 함수가 종료되지 않으므로 neverfunction f3(): never {
while (true) {
// ...
}
}
1) 아무 값도 반환하지 않음 void
2) 함수가 비정상적으로 종료되므로 never
3) 함수가 종료되지 않으므로 never
object
// 98.tslet v: object;
v = { name: "abc" };
console.log(v.prop1);// @ : 타입 에러 1) 객체의 속성에 대한 정보가 없기 때문에 접근하면 타입에러가 발생한다.// @ : 속성 정보를 포함해서 타입 정의하기 위해서 interface를 사용해야 한다.1) 객체의 속성에 대한 정보가 없기 때문에 접근하면 타입에러가 발생한다.
속성 정보를 포함해서 타입 정의하기 위해서 interface를 사용해야 한다.
교차 타입과 유니온 타입
// 99.ts// @ : 1) 타입은 3 | 5let v1: (1|3|5) & (3 | 5| 7)
v1 = 3;
// @ : 2) v1에는 3 또는 5가 아닌 값을 할당할 수 없음
v1 = 1;1) 타입은 3 | 5
2) v1에는 3 또는 5가 아닌 값을 할당할 수 없음
type 키워드로 타입에 별칭 주기
// 910.ts
type Width = number | string// @ : 1) number | string 타입에 Width라는 별칭 부여let width : Width;// @ : 2) 일반적인 타입처럼 사용
width = 100;
width = '100px';1) number | string 타입에 Width라는 별칭 부여
2) 일반적인 타입처럼 사용
922 열거형 타입
열거형 타입
// 911.ts// @ : 1) 열거형 타입을 이용하여 과일 정의
enum Fruit {
Apple,
Banana,
Orange,
}
// @ : 2) 열거형 타입의 원소인 Apple을 값으로 사용const v1: Fruit = Fruit.Apple;
console.log(typeof v1);// number// @ : 3) Apple을 타입으로 사용const v2: Fruit.Apple | Fruit.Banana = Fruit.Banana;
1) 열거형 타입을 이용하여 과일 정의
2) 열거형 타입의 원소인 Apple을 값으로 사용
3) Apple을 타입으로 사용
명시적으로 원소의 값 입력하기
// 912.ts
enum Fruit {
// @ : 1) enum의 첫번째에 값 할당하지 않으면 자동으로 0 할당
Apple,
// @ : 2) enum의 각 원소에 숫자 또는 문자열 할당 가능. 명시하지 않으면 이전 원소 + 1
Banana = 5,
Orange,
}
1) enum의 첫번째에 값 할당하지 않으면 자동으로 0 할당
2) enum의 각 원소에 숫자 또는 문자열 할당 가능. 명시하지 않으면 이전 원소 + 1
열거형 타입의 객체 사용하기
// 914.ts
enum Fruit {
Apple,
Banana = 5,
Orange,
}
// @ : 1) enum은 객체이므로 객체처럼 다룰 수 있다.console.log(Fruit.Banana);// 5console.log(Fruit["Banana"]);// 5// @ : 2) 각 원소의 이름과 값이 양방향 매핑되서 값으로 이름을 가져올 수 있다.console.log(Fruit[5]);// Banana1) enum은 객체이므로 객체처럼 다룰 수 있다.
2) 각 원소의 이름과 값이 양방향 매핑되서 값으로 이름을 가져올 수 있다.
열거형 타입의 값으로 문자열 할당하기
// 915.ts
enum Language {
Korean = "ko",
English = "en",
Japanese = "jp",
}
enum 의 원소에 문자열을 입력하는 경우에는 단방향 매핑된다. 이는 서로 다른 원소의 이름 또는 값이 같으면 충돌이 일어나기 때문이다.
열거형 타입을 위한 유틸리티 함수
// 917.tsfunction getEnumLength(enumObject: any) {
const keys = Object.keys(enumObject);
// @ : enum의 값이 숫자이면 두 개씩 들어가므로 문자열만 계산return keys.reduce(
// @ : 1) 원소가 숫자면 양방향 매핑이므로 주의. 객체의 속성값이 문자열인 경우만 계산하면 열거형의 원소 개수를 구할 수 있다.
(acc, key) => (typeof enumObject[key] === "string" ? acc + 1 : acc),
0
);
}
열거형 타입에 존재하는 값인지 검사하는 함수
// 918.tsfunction isValidEnumValue(enumObject: any, value: number | string) {
if (typeof value === "number") {
// @ : 1) 값이 숫자이면 양방향 매핑인지 검사한다.return !!enumObject[value];
} else {
return Object.keys(enumObject)
.filter((key) => isNaN(Number(key)))
// @ : 2) 값이 문자열이면 양방향 매핑에 의해 생성된 키를 제거하고 해당 값이 존재하는지 검사
.some((key) => enumObject[key] === value);
}
}
getEnumLength 함수와 isValidEnumValue 함수의 사용 예
// 919.tsimport isValidEnumValue from "./918";
import getEnumLength from "./917";
enum Fruit {
Apple,
Banana,
Orange,
}
enum Language {
Korean = "ko",
English = "en",
Japanese = "jp",
}
console.log(getEnumLength(Fruit), getEnumLength(Language));
// @ : 3 3 1) 열거형 타입 원소 개수 출력console.log("1 in Fruit:", isValidEnumValue(Fruit, 1));
// @ : 2) 열거형 타입에 존재하는 값이 맞는지 검사// @ : trueconsole.log("5 in Fruit:", isValidEnumValue(Fruit, 5));
// @ : falseconsole.log("ko in Language:", isValidEnumValue(Language, "ko"));
// @ : trueconsole.log("Korean in Language:", isValidEnumValue(Language, "Korean"));
상수 열거형 타입
열거형 타입은 컴파일 후에도 남아있기 때문에 번들 파일의 크기가 불필요하게 커진다. 열거형 타입의 객체에 접근하지 않는다면 삭제해도 된다. const 열거형 타입을 사용하면 된다.
// 923.tsimport getEnumLength from "./917";
const enum Fruit {
Apple,
Banana,
Orange,
}
// @ : 타입 에러 1) 열거형 타입을 상수로 정의하면 열거형 타입의 객체를 사용할 수 없다.console.log(getEnumLength(Fruit));