1. 배경
Javascript의 성장
- 처음에는 웹페이지에 간단한 상호작용을 넣기 위한 작은 스크립트 언어였음
- 현재는 프론트엔드 뿐 아니라 백엔드, 큰 규모의 앱에서도 사용됨
- ⚠️ 앱이 커질수록 실행 전에는 발견하기 어려운 타입 관련 오류가 많아짐
목표
- Javascript 코드를 실행하기 전 타입이 맞는지 검사하는 역할
- ✅ Javascript 문법을 그대로 쓰며, 거기에 Typescript의 타입 시스템이 추가됨
2. 타입
- 값이 할 수 있는 동작과 능력
Type Annotation
- 변수, 함수 파라미터, 반환값 등에 타입을 직접 적는 문법
- 타입을 지정할 대상 뒤에 타입을 적음
Object Type
- 객체가 어떤 속성을 가지고 있고, 각 속성이 어떤 타입인지 표현함
예시
더보기
function printCoord(pt: { x: number; y: number }) {
console.log(pt.x);
console.log(pt.y);
}
printCoord({ x: 3, y: 7 }); // 가능
printCoord({ x: 3 }); // 에러
Optional Property
- 객체 속성 중, 있어도 되고 없어도 되는 값은 선택 속성으로 표현함
예시
더보기
function printName(obj: { first: string; last?: string }) {
console.log(obj.first);
}
printName({ first: 'Bob' }); // 가능
printName({ first: 'Alice', last: 'Alisson' }); // 가능
Static type-checking
- 코드 실행 전에 타입을 검사함
Non-exception Failures
- 실행은 되지만 실수일 가능성이 높은 코드도 잡아줌
- ➡️ javascript에서는 에러 없이 undefined를 반환하는 코드도 Typescript는 오류로 볼 수 있음
예시) undefined
더보기
const user = {
name: 'Daniel',
age: 26,
};
user.location;
// JS: undefined
// TS: location 속성이 없다고 에러
Types for Tooling
- Typescript는 타입 정보를 알기 때문에 vscode같은 에디터가 여러 기능을 제공해줄 수 있음
- ex) 자동 완성, 오타 경고, 빠른 수정, 정의로 이동, 참조 찾기 등
Erased Types
- 타입 정보는 런타임에 사라지므로, 타입 표기는 실제 실행 동작을 바꾸지 않음
예시) undefined
더보기
const user = {
name: 'Daniel',
age: 26,
};
user.location;
// JS: undefined
// TS: location 속성이 없다고 에러
Strictness
- 타입스크립트를 얼마나 엄격하게 검사할 지 정하는 옵션
- ✅ noImplicitAny: 타입을 안적었는데 typescript가 추론 못해서 any로 쓰는걸 막음
- ✅ strictNullChecks: null/undefined 가능성 있으면 사용전 반드시 체크해야 함
설정) tsconfig.json
더보기
{
"compilerOptions": {
"strict": true
}
}
예시) strictNullChecks
더보기
type User = {
name: string;
};
let user: User | null = null;
console.log(user.name);
3. 핵심 개념
Types by Inference
- 값을 보고 Typescript가 알아서 타입을 추측함
예시
더보기
const count = 0; // number로 추론
const name = '영진'; // string으로 추론
const isLogin = true; // boolean으로 추론
Defining Types
- Typescript가 알아서 추론 못 하거나, 명확히 구조를 표현하고 싶을 때 타입을 직접 정의함
예시
더보기
정의
interface User {
name: string;
id: number;
}
사용
const user: User = {
name: 'Hayes',
id: 0,
};
함수 파라미터와 반환값에 타입 붙이기
예시
더보기
파라미터
function deleteUser(user: User) {
// ...
}
반환값
function getAdminUser(): User {
return {
name: 'Admin',
id: 1,
};
}
Composing Types
- 단순 타입을 조합해서 복잡한 타입을 만듬
- ✅ union: 여러 타입 중 하나
- ✅ generic: 타입을 함수의 파라미터처럼 받아서 재사용하는 문법
예시) union
더보기
type WindowStates = 'open' | 'closed' | 'minimized';
let state: WindowStates;
// 아래 3개만 가능
state = 'open';
state = 'closed';
state = 'minimized';
예시) generic
더보기
type StringArray = Array<string>;
type NumberArray = Array<number>;
type ObjectWithNameArray = Array<{ name: string }>;
직접 정의
interface Backpack<Type> {
add: (obj: Type) => void;
get: () => Type;
}
declare const backpack: Backpack<string>;
Structural Type System
- Typescript는 이름보다 객체의 모양을 봄
- 필요한 속성만 갖추고 있으면 해당 타입과 호환된다고 봄
예시) interface
더보기
interface Point {
x: number;
y: number;
}
function logPoint(p: Point) {
console.log(`${p.x}, ${p.y}`);
}
const point = { x: 12, y: 26 };
logPoint(point);
- point가 명시적으로 Point라고 선언되어있지 않았어도, 모양이 같아서 가능
예시) class
더보기
interface Point {
x: number;
y: number;
}
class VirtualPoint {
x: number;
y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
const newVPoint = new VirtualPoint(13, 56);
logPoint(newVPoint);
- newVPoint도 const newVPoint: Point로 구현했단 표시가 없음
- 그러나 Point 속성의 이름과 타입을 가지고 있으므로 newVPoint가 Point를 구현했다 봄
4. Interface vs Type
- 객체 모양을 정의하는 것은 둘다 같음
- ✅ interface: 객체 구조를 선언하는 데 주로 사용됨
- ✅ type: 객체 타입 뿐 아니라 union, primitive alias 등 더 넓게 사용 가능
예시) type
더보기
type SquareValue = 'X' | 'O' | null;
type UserId = number;
type UserName = string;
const userId: UserId = 1;
const userName: UserName = '영진';
출처