자바스크립트는 동적 언어로서 변수의 타입은 런타임에 결정된다. 동적/ 정적인 특징의 차이는 단순해 보이지만 개발할 때 고려할 것들은 많이 다르다.
이 블로깅은 typescript와 리액트에 타입 정보를 추가하는 방법에 대한 정리이다.
타입스크립트란 단순히 자바스크립트의 모든 기능을 포함하면서 정적 타입이 지원되는 언어이다.
먼저 동적 언어와 정적 언어를 비교해보면서 왜 정적인 언어인 타입스크립트가 인기가 많아지고 있는지 왜 자바스크립트에 정적 타입이 필요한지 살펴보겠다.
먼저 동적 타입 언어와 정적 타입 언어의 차이를 간단히 설명해보면
동적 타입 언어 | 정적 타입 언어 |
---|---|
타입에 대한 고민을 하지 않아도 되므로 배우기 쉽다 | 변수를 선언할 때마다 타입을 고민해야 하므로 진입 장벽이 높다 |
코드의 양이 적을 때 생산성이 높다 | 코드의 양이 많을 때 동적 타입 언어에 비해 생산성이 높다 |
타입 오류가 런타임 시 발견된다 | 타입 오류가 컴파일 시 발견된다 |
딱히 동적 / 정적 타입 언어 중 무엇이 뛰어나다고 할 수 없을 정도로 서로의 장단점이 다르다. 따라서 팀과 프로젝트의 성격에 따라 선택해야 한다고 책에서는 나온다.
정적 타입 언어의 코드는 타입으로 서로 연결되어 있다. 덕분에 연관된 코드 간의 이동이 쉽고, 변수명이나 함수명을 변경하는 등의 리팩토링이 쉽다.
Import를 하지 않고 코드를 작성해도 단축키 한 번이면 IDE가 필요한 임포트 코드를 자동으로 넣어 준다.
함수를 호출하기 위해 함수 이름과 괄호를 입력하면 함수의 매개변수 종류와 반환값의 타입을 확인할 수 있고 속성값의 종류가 많은 객체라 하더라도 객체 이름과 점을 입력하면 속성값 목록을 확인할 수 있다.
가장 큰 장점은 타입스크립트는 꾸준히 개발되고 업데이트 된다는 것이다. 즉 자바스크립트의 새로운 표준으로 나오는 기능들은 타입스크립트에도 빠르게 추가되고 리액트 개발자들의 의견을 잘 반영해 주기 때문에 JSX 문법과 리액트 컴포넌트의 타입을 정의하는 데 큰 어려움이 없다.
또한 마이크로소프트에서 개발중인 타입스크립트는 vscode와도 궁합이 좋은데 마이크로소프트에서 개발하는 IDE가 바로 vscode이기 때문이다.
결론적으로 리액트 개발자에다가 사용하는 IDE가 vscode라면 타입스크립트는 좋은 개발 환경이 될 것이다.
const size: number =123;
const isBig: boolean = size >=100;
const msg: string = isBig ? '크다' : '작다';
const values : number[] = [1,2,3];
const values2: Array<number> = [1,2,3];
values.push('a') // 타입에러
const data: [string, number] = [msg, size];
data[0].substr(1);
data[1].substr(1); // 타입에러
let v1: undefined = undefined;
let v2: null = null;
v1 = 123; // type error
let v3: number | underfined = undefined;
v3 = 123;
let v1: 10 | 20 | 30;
v1 = 10;
v1 = 15; // type error
let v2: "police officer" | "firefighter";
v2 = "doctor"; // type error
let value: any;
value = 123;
value = '456';
value = () => {};
any타입에는 숫자와 문자열 뿐만 아니라 함수도 입력될 수 있다.
기존 레서시 코드를 타입스크립트로 변환할 때 유용하다.
function f1(): void {
console.log('hello');
}
function f2():never {
throw new Error('some error');
}
function f3(): never {
while (true) {
// ...
}
}
아무 값도 반환하지 않고 종료되는 함수의 반환 타입은 void 타입으로 정의할 수 있다.
또한 비정상적으로 종료되거나 무한 루프 때문애 종료되지 않는 함수의 반환 타입은 never 타입으로 정의 할 수 있다.
let v: object;
v = { name: 'abe' };
console.log(v.prop1); // type error
위 예제에서 타입에러가 발생하는 이유는 객체의 속성에 대한 정보가 없이 때문이다. 속성 정보를 포함해서 타입을 정의하기 위해서는 interface를 사용해야한다.
여러 타입의 교집합과 합집합을 각각 교차타입(&)과 유니온 타입(|)으로 표현할 수 있다.
let v1: (1|3|5) & (3|5|7);
v1 =3;
v1 = 1; // type error
변수 v1의 타입은 3|5 이다 그렇기 때문에 1 을 할당하면 타입 에러가 발생하는 것이다.
type 키워드를 사용해서 타입에 별칭을 주어서 편리하게 사용가능하다.
type Width = number | string ;
let width: Width;
width= 100;
width = '100px';
이렇게 별칭을 지정하여 일반적인 타입처럼 사용 가능하다.
열거형 타입은 enum
키워드를 사용해서 정의할 수 있는데 값으로도 타입으로도 사용될 수 있다.
enum Fruit {
Apple,
Banana,
Oragne,
}
const v1: Fruit = Fruit.Apple;
const v2: Fruit.Apple | Fruit.Banana = Fruit.Banana;
v1
은 열거형 타입의 원소인 Apple을 값으로 사용했고
v2
는 Apple을 타입으로 사용하였다.
함수의 타입을 정의할때는 매개변수 타입 과 반환 타입이 필요하다.
콜론 (:)을 이용해서 매개변수 타입과 반환 타입을 정의할 수 있다.
function getInfoText(name: string, age: number): string {
const nameText = name.substr(0, 10);
const ageText = ageText = age >= 35? 'senior' : 'junior';
return `name: ${nameText}, age: ${ageText}`;
}
const v1: string = getInfoText('Mike', 23);
const v2: string = getInfoText('mike', '23'); //type error
const v3: number = getInfoText('mike', 23); //type error
------------------------------------------------------------------------
const getinfoText: (name:string, age:number) => string = function (name,age) {
// ...
}
handleClick =(name: string, age: number): string =>{
return `name: ${nameText}, age: ${ageText}`;
}
선택 매개변수는 반드시 입력하지 않아도 되는 매개변수이며 매개변수 이름 오른쪽에 물음표 기호를 입력하면 선택 매개변수가 된다.
function getInfoText(name:string, age:number, language?:string):string {
const nameText = name.substr(0, 10);
const ageText = ageText = age >= 35? 'senior' : 'junior';
const languageText = language ? language.substr(0,10) : "";
return `name: ${nameText}, age: ${ageText}, language: ${languageText};`
}
getInfoText('mike', 23, 'ko');
getInfoText('mike', 23);
getInfoText('mike', 23, 123); // type error
또한 선택 매개변수 오른쪽에 필수 매개변수가 오면 컴파일 에러가 발생하기 때문에
function getInfoText(name:string, language?:string | undefined, age:number):string {
const nameText = name.substr(0, 10);
const ageText = ageText = age >= 35? 'senior' : 'junior';
const languageText = language ? language.substr(0,10) : "";
return `name: ${nameText}, age: ${ageText}, language: ${languageText};`
}
undefined
도 입력해야한다.