타입스크립트는 자바스크립트에 변수, 매개변수, 리턴값에 타입 붙여놓는 것 정도로 생각하면 편함
const a: number = 5;
const b: string = '5'
const c: boolean = true
const d: undefined = undefined
const e: null = null
const f: symbol = Symbol.for('f')
const g: bigint = 1000000n
const h: any = any // typescript가 아닌 javascript를 사용하는 격
// 리터럴 타입 (type은 보다 정확하게)
const i: 5 = 5;
const j: true = true;
// 패러미터, 리턴값에 타입 붙이기
function add(x: number, y: number): number { return x + y }
const add: (x: number, y: number) => number = (x, y) => x + y;
const obj: { lat: number, lon: number } = { lat: 37.5, lon: 127.5 };
// 배열
const arr: number[] = [123, 456]
// 아래와 같은 방식으로도 사용 가능
// const arr: Array<number> = [123, 456]
// tuple
const arr2: [number, number, string] = [123, 456, 'abc']
type
으로 타입을 선언하는 방식
type Add = (x: number, y: number) => number
interface
로도 타입 선언이 가능
interface Add {
(x: number, y: number): number
}
위의 코드에서 타입을 지워도 에디터 자체에서 타입을 제대로 처리하고 있다면 그냥 에디터에서 결정한 타입 사용하는게 좋음
타입이 있는 곳에서 타입을 생략하는 쪽으로 코드 작성해보기
const a: string = '5'
// 튜플로 사용하려고 했는데 음...
const arr = [123, 456, 'avc']
// 이런 경우에 타이핑
const arr: [number, number, string] = [123, 456, 'avc']
'5'로 type narrowing을 할 수 있는데 이걸 string으로 타입을 넓힘 (부정확한 타입 사용)
정의된 타입과 ts 파일에서 사용된 타입들을 삭제한다
// 정의부와 구현부를 따로 둔다
// 정의부는 js에서 삭제
function add(x: number, y: number): number
function add(x, y) { return x + y }
// as문도 삭제
let aa = 123
aa = 'hello' as unknown as number // 강제 형변환
빈 배열은 never로 처리하기 때문에 typing을 반드시 해줘야됨
try {
const array: string[] = []
array.push('hello')
} catch(error) {
error
}
const head = document.querySelector('#head')!; // Element | null인데...?
// null 절대 아님, 진짜로(not-null assertion) => !
console.log(head);
// 제발 안전하게 사용해 (if 사용하기)
const head = document.querySelector('#head');
if (head) {
console.log(head);
}
// 객체 래퍼 타입은 웬만하면 쓰지마
const hell: String = 'hell'
const whenToUse = new String('in here')
type World = 'world' | 'hell'
const a: World = 'world'
type Greeting = `hello ${World}`
const b: Greeting = 'hello world' // 이렇게 추천받을 수 있음
function rest(...args: string[]) {
console.log(args) // [1, 2, 3]
}
rest('1', '2', '3');
const tuple: [string, number] = ['2', 3]
// 얜 막아줌
tuple[2] = 4
// 근데 이건 못 막아줌
tuple.push(4)
// 값도 지정 가능
// js에서 사라지는 코드
const enum EDirection {
Up, Down, Left, Right
}
// 이 정의는 남아있음
// 웬만하면 남기는게 좋을 수 있음
// as const를 지우면 readonly + number로 typing 됨
const ODirection = {
Up: 0,
Down: 1,
Left: 2,
Right: 3
} as const
const a = EDirection.Up
// enum
function walk(dir: EDirection) {}
// as const
// keyof는 객체의 key를 가져오기
// 아래의 정의는 value들만 typing하기
type Direction = typeof ODirection[keyof typeof ODirection]
function run(dir: Direction) {}
const obj = { a: 1, b: 2, c: 3 }
// typeof obj => { a: number, b: number, c: number }
// keyof typeof obj => "a" | "b" | "c"
type Key = keyof typeof obj
type A = string | number
// 둘 다 가능
const a: A = 2
const b: A = '2'
function add(x: string | number, y: string | number): string | number { return x + y }
위 함수는 리턴값에 대한 타이핑이 오류라고 나옴
const result = add(1, 2)
result는 number인데 string으로도 착각할 수 있는 문제가 발생함 이러면
result.charAt(2)
이런 경우에 제대로 동작이 안되는 경우가 있음
type A = string & number
const a: A = 1; // 되겠냐
// 객체는 아래 prop을 모두 가져야 한다
// union은 아래 속성 중 하나만 가지고 있으면 된다
type A = { hello: 'world' } & { zero: 'cho' }
const a: A = { hello: 'world', }
type Animal = { breathe: true }
type Human = Animal & { think: true }
// 둘 다 있어야 한다고
const nunu: Human = { breathe: true, think: true }
위의 방식말고도 기존 타입을 확장시키는 방식이 더 있음
interface Animal {
breathe: true
}
interface Human extends Animal {
think: true
}
interface A {
talk: () => void
}
interface A {
eat: () => void
}
interface A {
shit: () => void
}
const a: A = { talk() {}, eat() {}, shit() {} }