
if(typeof text !== 'string') throw '문자열 아님';
자바스크립트는 위와 같은 예외 처리로 검사를 해야한다. 하지만 if문을 이용한 타입 검사가 많아질수록 런타임에 불필요한 타입 검사를 하게 된다.
타입스크립트를 사용한다면 이러한 자바스크립트의 단점?을 보완할 수 있다.
//add.js
function sum(a,b) {
return a + b;
};
sum(10, 20); //30
sum('10', '20') //1020
//add.ts
function sum(a:number, b:number){
return a + b;
};
sum('10','20'); // Error: '10'은 number에 할당될 수 없습니다.
javascript로 작성하였을 때, 인자로 string이 들어가 의도하지 않은 코드가 동작한 것을 알 수 있다.
ts에서 인자를 동일하게 string으로 적용할 경우 typescript의 오류를 확인할 수 있다.
컴파일 단계에서 오류를 포착할 수 있고 명시적인 정적타입 지정은 개발자의 의도를 명확하게 코드로 기술할 수 있다. 이는 코드의 가독성을 높이고 예측할 수 있게 하며 디버깅을 쉽게 한다.
interface PersonInterface {
name: string
age: number
}
const me1: PersonInterface = {
name: 'rain',
age: 20,
}
type PersonType = {
name: string
age: number
}
const me2: PersonType = {
name: 'rain',
age: 30,
}
//interface 확장 방법
interface PeopleInterface {
name: string
age: number
}
interface StudentInterface extends PeopleInterface {
school: string
}
//type의 확장 방법
type PeopleType = {
name: string
age: number
}
type StudentType = PeopleType & {
school: string
}
여기서 두개의 확실한 차이는 type은 새로운 속성을 추가하기 위해서 다시 같은 이름으로 선언할 수 없고, interface는 항상 선언적 확장이 가능하다는 것이다.
// interface
interface Window {
title: string
}
interface Window {
ts: TypeScriptAPI
}
// 같은 interface 명으로 Window를 다시 만든다면, 자동으로 확장이 된다.
const src = 'const a = "Hello World"'
window.ts.transpileModule(src, {})
//type
type Window = {
title: string
}
type Window = {
ts: TypeScriptAPI
}
// Error: Duplicate identifier 'Window'.
// 타입은 안된다.
interface FooInterface {
value: string
}
type FooType = {
value: string
}
type FooOnlyString = string
type FooTypeNumber = number
interface fooOnlyString = string (x)
type names = 'firstName' | 'lastName'
type NameTypes = {
[key in names]: string
}
const yc: NameTypes = { firstName: 'hi', lastName: 'yc' }
interface NameInterface {
// error
[key in names]: string
}
interface는 객체의 타입을 만들기 위한 것이다.
type의 경우 원시 타입이 올 수 있다. type의 경우merge하게 되는 경우 재귀적으로 순회하며 속성을 merge한다고 한다.
type type2 = { a: 1 } & { b: 2 } // 잘 머지됨
type type3 = { a: 1; b: 2 } & { b: 3 } // resolved to `never`
const t2: type2 = { a: 1, b: 2 } // good
const t3: type3 = { a: 1, b: 3 } // Type 'number' is not assignable to type 'never'.(2322)
const t3: type3 = { a: 1, b: 2 } // Type 'number' is not assignable to type 'never'.(2322)
그러므로 타입 간 속성을 머지 할 경우, 어차피 객체에서만 쓰는 용도라면, interface를 쓰는 것이 훨씬 낫다고도 한다. 또한 공식 문서에서도 interface 사용을 권장한다고 한다. 기본적으로 인터페이스로 표현할 수 있는 모든 타입은 인터페이스로 표현하고, 기본 타입에 새로운 이름을 붙이고 싶거나 유니온 타입을 명명하고 싶은 경우 등 인터페이스의 능력 밖인 부분에서만 타입 별칭을 사용하는 것이 좋다.
import React from 'react';
interface GreetingsProps {
name: string;
mark: string;
optional?: string;
onClick: (name: string) => void; // 아무것도 리턴하지 않는다는 함수를 의미합니다.
};
function Greetings({ name, mark, optional, onClick }: GreetingsProps) {
const handleClick = () => onClick(name);
return (
<div>
Hello, {name} {mark}
{optional && <p>{optional}</p>}
<div>
<button onClick={handleClick}>Click Me</button>
</div>
</div>
);
}
Greetings.defaultProps = {
mark: '!'
};
export default Greetings;
import React from 'react';
import Greetings from './Greetings';
const App: React.FC = () => {
const onClick = (name: string) => {
console.log(`${name} says hello`);
};
return <Greetings name="Hello" onClick={onClick} />;
};
export default App;
interface Backpack<Type> {
add: (obj: Type) => void;
get: () => Type;
}
// This line is a shortcut to tell TypeScript there is a
// constant called `backpack`, and to not worry about where it came from.
declare const backpack: Backpack<string>;
// object is a string, because we declared it above as the variable part of Backpack.
const object = backpack.get();
// Since the backpack variable is a string, you can't pass a number to the add function.
backpack.add(23);
Argument of type 'number' is not assignable to parameter of type 'string'.
declare namespace MainType {
type VolumeData = {
searchingDate: string;
volume: MainAllVolume[];
volume_down: MainDownUp[];
volume_up: MainDownUp[];
volume_bar: KapiVolumeBar[];
};
type PriceData = {
price: MainPrice[];
price_down: MainPrice[];
price_up: MainDownUp[];
};
};
export default MainType;
import React from "react";
import MainType from "../apiclient/types/main";
type State = {
volumeData: MainType.VolumeData | null;
priceData: MainType.PriceData | null;
};
export default class Main extends React.Component<{}, State> {
state: State = {
volumeData: null,
priceData: null,
};
...
}
참고 사이트