Typescript 6. 객체의 타입

하비·2024년 3월 21일
0

typescript

목록 보기
6/14

객체의 타입

Object

객체는 구조적 타입 시스템을 갖고 있기 때문에 객체 안의 구조를 타입으로 지정해줘야 함.

  1. 객체 리터럴 타입
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')
  1. optional Property
    선택적으로 값이 없을 수 있는 항목에 대해선 optional을 적용할 수 있다.
let dog:{nickName:string, age:number, cute?: boolean}={
  nickName:'몽실이',
  age: 3,
  cute: true,//값이 없어도 에러가 뜨지 않음
}
  1. 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
  1. 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
}
  1. 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을 써보는 것을 추천한다

  1. 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;
}//이러면 에러가 안뜸

profile
개발자를 꿈꾸는 하비입니다

0개의 댓글