객체는 구조적 타입 시스템을 갖고 있기 때문에 객체 안의 구조를 타입으로 지정해줘야 함.
- 객체 리터럴 타입
let dog:{nickName:string, age:number, cute: boolean}={ nickName:'몽실이', age: 3, cute: true, }
객체의 리터럴 타입 사용 시 주의해야할 점은test2.name
의 타입은 literal 타입 'song'이 아닌 string이라는 것을 생각해야 한다.
때문에 func2의 매개변수로test2.name
을 쓰려면test2.name
의 타입을 리터럴로 정의해줘야 하는데 방법으론 3가지가 있다.
as const
를 붙이면 그 안의 것들이 readonly로 정의되어 고정값이 됨//assertion 사용 시, func2(test2.name as 'song')
- optional Property
선택적으로 값이 없을 수 있는 항목에 대해선 optional을 적용할 수 있다.let dog:{nickName:string, age:number, cute?: boolean}={ nickName:'몽실이', age: 3, cute: true,//값이 없어도 에러가 뜨지 않음 }
- readonly property
값이 절대 바뀔 수 없는 경우 readonly를 사용하여 freeze 할 수 있다.
사용할 경우 첫번째 선언한 값이 고정되어 다른 값으로 바꾸려 할 시 에러가 발생함.let dog:{ readonly nickName:string, age:number, cute?:boolean } = { nickName:'몽실이', age:3, cute:true } dog.nickName = '멍멍이'//error: Cannot assign to 'nickName' because it is a read-only property
- Type alias
동일한 타입이 필요한 경우 타입에 별칭을 부여해 재사용할 수 있다.type User = { id:number, nickName:string, auth:string, isPayed:boolean } let user1:User = { id:1, nickName:'tiger', auth:'admin', isPayed:true } let user2:User = { id:2, nickName:'another', auth:'student', isPayed:false }
- Interface
동일한 타입이 필요한 경우 인터페이스를 사용해서도 재사용이 가능하다.
타입 스크립트에서만 지원함.
또한 interface 정의 시 앞을 대문자로 하는 것을 추천한다.
인터페이스를 사용하면 객체의 타입을 정의하고자 한다는 것이 명확해져 객체의 정의 시 인터페이스를 많이 사용함interface User { id:number, nickName:string, auth:string, isPayed:boolean //interface 안에서 메서드 정의하기 greet():void//함수와 결과값 greetTwo(one:string):void//인수의 타입 정의 역시 가능 } let user1:User = { id:1, nickName:'tiger', auth:'admin', isPayed:true } let user2:User = { id:2, nickName:'another', auth:'student', isPayed:false }
type alias와 interface의 차이점
타입 별칭과 인터페이스는 매우 유사하며, 대부분의 경우 둘 중 하나를 자유롭게 선택해서 사용할 수 있다. interface
가 가지는 대부분의 기능은 type
과 유사하나, 가장 핵심적 차이는 새 프로퍼티의 추가할 수 있는 개방 여부이다.
타입은 생성된 뒤에는 달라질 수 없으나, 인터페이스는 extends
통한 확장이나, 기존의 인터페이스에 새 필드를 추가하는 게 가능하다.
type에서도 interface에서도 readonly를 사용할 수 있음.
//인터페이스의 extends를 통한 확장
interface Animal {
name: string
}
interface Bear extends Animal {
honey: boolean
}
const bear = getBear()
bear.name
bear.honey
//type의 교집합(&)을 통한 확장
type Animal = {
name: string
}
type Bear = Animal & {
honey: Boolean
}
const bear = getBear();
bear.name;
bear.honey;
//기존의 인터페이스에 새 필드 추가하기
interface Window {
title: string
}
interface Window {
ts: TypeScriptAPI
}
const src = 'const a = "Hello World"';
window.ts.transpileModule(src, {});
//type은 생성된 뒤에는 달라질 수 없음
type Window = {
title: string
}
type Window = {
ts: TypeScriptAPI
}
// Error: Duplicate identifier 'Window'.
//type의 함수 선언
type AddFn = (a:number, b:number)=>number;
let add: AddFn
add = (n1:number, n2:number) => {
return n1+n2;
}
//interface의 함수 선언
interface AddFn{
(a:number, b:number):number;
}//객체 안에 소괄호로 매개변수와 콜론으로 결과값을 정의한다
let add: AddFn
add = (n1:number, n2:number) => {
return n1+n2;
}
일단 interface
를 사용해 보고 문제가 생길 시 type
을 써보는 것을 추천한다
- Index signatures
객체의 key와 value의 값을 개수에 상관없이 받고 싶을 때 사용한다.
다른 속성과 같이 사용 가능,(허나 논리적으로 말이 되어야 함)type code = {[key: string]: number;}; let keyCode: code = { enter: 13, backspace: 8, tab: 9, ctrl:17, pageUp:33 }; //다른속성과 같이 사용시 type code = {
[key:string]:string;
example: number;
}//이 경우 에러가 뜸
type code = {
[key:string]:string | number;
example: number;
}//이러면 에러가 안뜸