React Docs 에 따라서
npx create-react-app my-app --template typescript
로 bash 창이나 cmd 창에서 실행 시키면 됩니다.
React + TypeScript 프로젝트를 최초 생성하면 tsconfig.json 설정을 조금 수정해 주어야 합니다.
보시는 것처럼 target: "es5"
와 lib: []
설정이 있는데 각각 이부분에 es6
로 변경하고 추가해 주겠습니다.
let car:string = "bmw" // 타입 지정 해줘야 한다.
car = 3 // -> string 으로 타입 지정 했는데 3인 숫자 넣어서 오류
처럼 타입스크립트의 기본은 변수에 타입을 지정하는 것입니다.
let car = "bmw"
타입 지정없이 변수를 선언했을 때 위 코드의 car 의 타입은 string
이 됩니다.
변수를 선언하거나 초기화 할때 타입이 추론되고, 이외에도 변수, 속성, 인자의 기본 값, 함수의 반환 값 등을 설정할 때 타입의 추론이 발생합니다.
오류 발생을 대비해 기본적으로 모든 타입을 지정해 주는 것이 적절합니다.
let age:number = 30;
let isAdult:boolean = true;
// 숫자배열
let a:number[] = [1,2,3]
let a2:Array<number> = [1,2,3]
// 문자배열
let week1:string[] = ["mon", "tue", "wed"]
let week2:Array<string> = ["mon", "tue", "wed"]
//튜플
leb b:[string, number];
b = ["z", 1] // 가능
b = [1, "z"] // 불가능
기본적인 타입 선언 방식이며, 배열의 경우 2가지 방식으로 선언이 가능합니다.
튜플의 경우 0번값과 1번값의 타입을 지정해 두었으니 다른 타입이 들어가면 error가 발생합니다.
return
이 없어 반환값이 없는 경우의 함수를 void
타입으로 지정합니다.function cons():void {
console.log("123")
}
function showError():never {
throw new Error()
}
function infLoop():never {
while (true) {
// do something..
}
}
쉽게 말하자면 비슷한 값들을 묶어준 타입이라 생각하시면 됩니다.
enum Direction {
Up = 1,
Down,
Left,
Right,
}
여기서 up
을 1로 초기화된 숫자로 선언해 주었습니다.
그 지점부터 Down, Left, Right 는 자동으로 증가된 값을 갖습니다.
즉 Direction.Up 은 1, Down 은 2, Left 는 3, Right 는 4 의 값을 가지게 됩니다.
다른경우로 처음부터 초기화 하지 않아도 됩니다.
enum Direction {
Up,
Down,
Left,
Right,
}
위 코드에서 up은 자동으로 0을 할당 받게 됩니다. 그 이후는 자동으로 증가된 값인 1,2,3 을 할당 받습니다.
마찬가지로 문자열 역시 enum
타입으로 지정이 가능합니다.
enum Os {
window = "win",
Ios = "ios",
Android = "android"
}
이처럼 비슷한 형태로 묶인 경우 enum
타입을 사용하게 됩니다.
숫자와 문자를 섞어서 사용할 수 있지만 굳이 그렇게 할 이유는 없습니다.
enum BooleanLikeHeterogeneousEnum {
No = 0,
Yes = "YES",
}
확실하게 JavaScript 런타임에서 장점을 취하려는 것이 아니라면, 이렇게 사용하지 않는 것을 권장합니다.
더욱 자세한 보기는 TypeScript Handbook 을 참조 하시면 됩니다.
타입스크립트에서
null
과undefined
역시 하나의 타입이자 값 입니다.
let a:null = null;
let b:undefined = undefined;
하지만 null
타입으로 설정한 변수에 null
이 아닌 다른 값이 할당되면 오류를 출력합니다.
이처럼 오류에 대해 엄격하게 출력하는 이유는 tsconfig.json 에 설정값 때문입니다.
"strictNullChecks": true, /* 엄격한 null 검사 사용 */
object
에 담긴 property
를 뽑아 쓰는 경우 예를 들어 user
에 name
과 age
가 담겨 온 경우 뽑아 쓰기 위해서는 user.name
으로 사용하면 되지만 타입스크립의 경우에는 그렇게 작성하면 에러가 날 수 있습니다. 이를 해결하기 위한 것이 Interface 타입입니다.interface User {
name: string,
age: number,
}
let user:User = {
name: "swan",
age: 10
}
console.log(user.name)
console.log(user.age)
위와 같이 User
타입을 지정하고 해당 타입을 받아오는 인자에 넣어 형식을 맞춰 주어야 오류가 발생하지 않습니다.
Interface 타입에서 해당 타입을 사용하거나 사용하지 않는경우 ?
를 통해 오류를 방지할 수 있습니다.
interface User {
name: string,
age: number,
gender? : string,
}
let user:User = {
name: "swan",
age: 10
}
user.gender = "male"
console.log(user.name)
console.log(user.age)
console.log(user.gender)
위 코드에서 User
타입에 gender
속성을 옵셔널체이닝 형식으로 지정하였습니다.
만약 옵셔널체이닝 없이 gender
속성에 string
을 사용하였다면 let user:User
변수는 에러를 반환합니다.
또한 위 코드처럼 user
변수 선언 후 아래에 새롭게 user.gender
로 선언해 주어도 에러가 나지 않습니다.
function hello(name: string, age?:number):string {
if (age !== undefined) {
return `Hello, ${name}. You are ${age}.`
} else {
return `Hello, ${name}`
}
}
함수를 정의할 때에도 옵셔널 체이닝을 사용 가능합니다.
위 코드에서 name
과 age
를 인자로 넘겨받는데 옵셔널체이닝을 이용하여 age
의 여부를 처리하였습니다.
만약 hello
함수가 실행될 때 age
가 들어오지 않는다면 age
는 undefined
타입으로 넘어오게 됩니다.
주의할 점
위 코드에서 옵셔널체이닝을 활용하여
필수 매개변수
와선택적 매개변수
를 동시에 사용하는 함수를 작성하였습니다.
이때선택적 매개변수
를 함수의 앞에 정의한다면 에러를 반환합니다. 반드시필수 매개변수
를 앞쪽에 써주어야 합니다.
함수의 넘겨받는 파라미터에 기본값을 설정한다면 옵셔널체이닝과 동일한 효과를 나타냅니다.
function hello(name="hello") {
return `Hello, ${name}`
}
여기서 아래에 const result = hello()
형식으로 함수를 정의한 뒤 사용해 주어도 에러가 나지 않습니다.
hello()
함수에 name
값이 옵셔널체이닝 형태가 되었기 때문입니다.
const result2 = hello(name='hi')
형식으로 사용하여도 에러가 발생하지 않습니다.
interface User {
name: string,
age: number,
gender? : string,
readonly birthyear: number
}
let user:User = {
name: "swan",
age: 10,
birthyear = 2000,
}
user.gender = "male"
// 오류: 상수나 읽기 전용 속성은 대입(assignment) 표현식의 좌항이 될 수 없음
user.birthyear = 1999 // -> 이건 readonly 형식을 재정의 하는거라 에러난다.
console.log(user.name)
console.log(user.age)
console.log(user.gender)
여기서 birthyear
을 읽기 전용 타입으로 지정해 주었습니다.
그 후 user
변수에서 birthyear
을 2000
으로 지정해 주었습니다. 근데 아래에서 새로이 1999
로 정의한다면 에러를 반환합니다.
interface Car {
color: string,
wheels: number,
start(): void
}
Car
타입을 위 코드와 같이 정의 하였을 때
interface Benz extends Car {
door: number;
stop() : void
}
이렇게 extends
를 활용하여 Car
타입을 불러와 새로이 타입을 재정의 하였습니다.
이렇게 사용한다면 Car
타입에 정의한 color, wheels, start
를 사용 가능합니다.
interface Car {
color: string,
wheels: number,
start(): void
}
interface Toy {
name: string,
}
interface ToyCar extends Car, Toy {
price: number,
}
또 이런식으로 여러개를 ,
로 구분하여 사용 가능합니다.