// 타입간의 관계
class Animal {}
class Bird extends Animal {
chirp() {}
}
class Crow extends Bird {
caw() {
}
}
function chirp(bird: Bird): Bird {
bird.chirp()
return bird
}
// chirp(new Animal) // 에러..
chirp(new Bird)
chirp(new Crow)
// 타입 넓히기
const af = 'x' // 'X'
let bf = af // string
const c: 'x' = 'x' // 'x'
let d = c // 'x'
// null 이나 undefined로 초기화된 변수는 any 타입으로 넓혀진다.
let a = null // any
a = 3 // any
// null or undefined로 초기화된 변수가 선언 범위를 벗어나면 타입 스크립트는 확실한(좁은) 타입을 할당한다.
function xString() {
let a = null // any
a = 3 // any
a = 'b' // any
return a
}
xString() // string
// const 타입
// 타입스크립트는 타입이 넓혀지지 않도록 해주는 const라는 특별 타입을 제공한다.
// 초과 프로퍼티 확인
type Options = {
baseURL: string,
cacheSize?: number,
tier?: 'prod' | 'dev'
}
class API {
constructor(private options: Options) {}
}
new API({
baseURL: 'https://api.mysite.com',
tier: 'prod'
})
new API({
baseURL: 'https://api.mysite.com',
tierr: 'prodprod' // 에러가 발생
})
type Unit = 'cm' | 'px' | '%'
// 정제
type Width = {
unit: Unit,
value: number
}
let units: Unit[] = ['cm', 'px', '%']
function parseUnit(value: string): Unit | null {
for (let i = 0; i < units.length; i++) {
if (value.endsWith(units[i])) {
return units[i]
}
}
return null
}
function parseWidth(width: number | string | null | undefined): Width | null {
if (width == null) {
return null
}
if (typeof width === 'number') {
return { unit: 'px', value: width}
}
let unit = parseUnit(width)
if (unit) {
return { unit, value: parseFloat(width)}
}
return null
}
type UserTextEvent = { value: string, target: HTMLInputElement }
type UserMouseEvent = { value: [number, number], target: HTMLElement }
type UserEvent = UserTextEvent | UserMouseEvent
function handle(event: UserEvent) {
if (typeof event.value === 'string') {
event.value //string
event.target // HTMLInputElemnt | HTMLElement
return
}
event.value // [number, number]
event.target // HTMLInputElemt | HTMLElement (!!!)
}
type UserTextEvent = { type: 'TextEvent' value: string, target: HTMLInputElement }
type UserMouseEvent = { type: 'UserMouseEvent' value: [number, number], target: HTMLElement }
type UserEvent = UserTextEvent | UserMouseEvent
function handle(event: UserEvent) {
if (event.type === 'TextEvent') {
event.value //string
event.target // HTMLInputElemnt
return
}
event.value // [number, number]
event.target // HTMLElement (!!!)
}
// 종합성
type Weekday = 'Mon' | 'Tue' | 'Wed' | 'Thu' | 'Fri'
type Day = Weekday | 'Say' | 'Sun'
function getNextDay(w: Weekday): Day {
switch (w) {
case 'Mon' : return 'Tue'
}
}
function isBig(n: number) {
if (n > 100) {
return true
}
}
// 키인 연산자
type APIResponse = {
user: {
userId: string
friendList: {
count: number: {
firstName: string
lastName: string
}
} []
}
}
function renderFriendList(friendList: unknown) {
}
type FriendList = {
count: numberfriends: {
firstName: string
lastName: string
}
}
type APIResponse = {
user: {
friendList: FriendList
}
}
function renderFriendList(friendList: FriendList) {
}
type FriendList = APIResponse['user']['friendList']
function renderFriendList(friendList: FriendList) {
}
// keyof 연산자
// keyof를 이용하면 객체의 모든 키를 문자열 리터럴 타입 유니온으로 얻을 수 있다.
type ResponseKeys = keyof APIResponse // 'user'
type UserKeys = keyof APIResponse['user'] // 'userId' | 'friendList'
type FriendListKeys = keyof APIResponse['user']['friendList'] // 'count' | 'friends'
function get<O extends object, K extends key of O> (o: 0, k: K): O[K] {
return o[k]
}
// 여기 까지 수정
type ActivityLog = {
lastEvent: Date
events: {
id: string
}
}
// Record 타입간의 - 타입스크립트의 내장 Record 타입을 이용하면 무언가를 매핑하는 용도로 객체를 활용할 수 있다.
type Weekday = 'Mon' | 'Tue' | 'Wed' | 'Thu' | 'Fri'
type Day = Weekday | 'Sat' | 'Sun'
let nextDay: Record<Weekday, Day> = {
Mon: 'Tue'
}
// 내장 매핑된 타입간의
// Record<Keys, Values> : keys타입의 키와 values 타입의 값을 갖는 객체
// Partial<Object> Object의 모든 필드를 선택형으로 표시
// Required<Object> Obejct의 모든 필드를 필수형으로 표시
// Readonly<Object>
// Pick<Object, Keys>
// 6.3.4 컴패이언 객체 패턴 : 스칼라에서 유래한 기능으로 같은 이름을 공유하는 객체와 클래스를 쌍으로 연결한다. 타입스크립트에는 타입과 객체를 쌍으로 묶는, 비슷한 기능의 비슷한 패턴이 존재하는데 이 역시도 컴패니언 객체 패턴의 예다.
type Currency = {
unit: 'EUR' | 'GBP' | 'JPY' | 'USD'
value: number
}
let Currency = {
DEFALT: 'USD'
from(value: number, unit = Currency.DEFAUTL): Currency {
return { unit, value }
}
}
let amountDue: Currency = {
unit: 'JPY',
value: 83733.10
}
let otherAmountDue = Currency.from(330, 'EUR')
// 고급 함수 타입들
// 튜플의 타입 추론 개선
function isString(a: unknown): boolean {
return typeof a === 'string'
}
function isString2(a: unknown): a is string {
return typeof a === 'string'
}
// 6.5 조건부 타입
type IsString<T> = T extends string ? true | false
type A = IsString<string> // true
Type B = IsString<number> // false
// 6.5.1 분배적 조건부
type ToArray<T> = T[]
type A = ToArray<number> // number[]
type B = ToArray<number | string> // (number | string)[]
type ToArray2<T> = T extends unknown ? T[] : T[]
type A = ToArray2<number> // number[]
type B = ToArray2<number | string> // number[] | string[]