ts 함수 매개변수의 속성 타입

mangorovski·2022년 12월 3일
0

아래 예문에서 함수는 object[]를 타입이다.
매개변수도 타입을 정의해줬는데, 함수 내부에서 파라미터의 속성의 타입이 없다는 에러를 발견했을 때의 오류는 어떻게 해결해야 할까?

parameter의 타입이 object일 때

let todoItems: object[];

function completeTodo(index:number, todo:object):void {
  todo.done = true;
  todoItems.splice(index, 1, todo);
}

todo.done의 부분 done이 빨간 밑줄이 생기는데 속성의 타입이 없다고 한다.
이럴때는 객체의 형태를 구체적으로 타입을 정의해줘야 한다.

let todoItems: {{id:number, title: string, done: boolean}}[];

function completeTodo(index:number, todo?:{id:number, title: string, done: boolean}):void {
  todo.done = true;
  todoItems.splice(index, 1, todo);
}

이제 중복되는 코드 부분을 정리해보자

let todoItems: {
  id:number
  title: string
  done: boolean
}[];

todoItems의 object부분은 다른 함수에서도 매개변수나 반환값으로도 쓰이고 있다.
이럴때는 타입별칭을 사용해서 타입을 먼저 선언해 준다.

type Todo = {
  id:number
  title: string
  done: boolean
}


let todoItems: Todo[];

Todo를 선언하고 사용하는 곳에 Todo라고 타입을 지정해주면 된다.
또는 interface를 사용한다.

interface는 타입스크립트에서 가장 핵심이다.
이제 Todo라는 값을 이용해서 중복되는 부분을 줄여나갈 수 있다.


interface란?

인터페이스는 반복되는 타입에 대해서 하나의 interface를 만들고 사용한다. 동일한 규칙을 쓰겠다는 상호간의 약속을 의미한다.

  • 객체의 스펙(속성과 속성의 타입)
  • 함수의 파라미터
  • 함수의 스펙(파라미터, 반환 타입)
  • 배열과 객체를 접근하는 방식
  • 클래스

[객체 속성과 속성의 타입]

// bin라는 변수는 User라는 interface를 받는다. 
// interface User는 객체의 스펙이 정의됨

interface User{
    name: string
    age: number
}

const bin : User = {
    age: 33,
    name: '비니'
}
  • 함수의 파라미터에 인터페이스 활용
    함수의 인터페이스를 활용할 때 파라미터에 정의를 확인하고
    함수 호출시 인자가 파라미터에 정의한 인터페이스의 규칙에도 맞는지 확인한다.

아래 getUser()함수는 User의 인터페이스를 가져야한다.

function getUser(user:User) {
    console.log(user)
}


// const capt = {
//     name: 'bin'
// } error
const capt = {
    name: 'bin',
    age: 33
}
getUser(capt)

[함수 구조에 인터페이스 활용]

함수의 전체적인 모습도 인터페이스로 정의할 수 있다.

const sumFun ={
	(a: number, a:number):number
}


//화살표 함수로 사용했을 때
const sum = (a, b):sumFun => {
	return a + b
}

//or
let sum: sumFun
sum = function(a, b){
	return a + b
}

// 위 함수는 이런 모습이다.
sum = function(a:number, b:number):number{
	return a + b
}

[배열에 인터페이스 활용]

  • 인덱싱 방식을 정의하는 인터페이스
interface stringArr {
    [index: number]: string
    // 배열에 접근하는 방식
}

const arr:stringArr = ['a', 'b']
arr[0] = 10 //stringArr에 맞지 않음

stringArr는속성은 이름이 정해져 있지 않다.
(위에서는 임의로 index라고 넣어줌)

배열에 대한 정의를 []괄호 안에 넣고, 해당 속성의 타입을 지정해 줄 수 있다.

  • 인터페이스 딕셔너리 패턴
    인덱싱과 유사하다. 해당 key에 대한 타입과 속성에 대한 타입을 interface에 정의해준다.
interface StringRegexDictionary{
    [key: string]: RegExp
    // [속성의 이름: 속성 타입]: 
}

// 정규식을 갖고 있는 객체 생성
const obj: StringRegexDictionary = {
    // cssfile: 'css' 정규식이 아니기에 error발생 
    
    cssfile: /\.css$/,
    jsfile: /\.js$/
}

장점?
obj에 있는 key만 forEach로 돌렸다. value는 모두 string 타입이다. 타입스크립트가 자동으로 추론을 해준다.

Object.keys(obj).forEach((value) => {
    console.log(value) //string
})

만일 객체에 접근했을 때 정해놓은 인터페이스에 어긋날 경우를 바로 캐치할 수 있다.

obj['cssfile'] = 'a' //RegExp타입이 아니라 오류가 나옴

[인터페이스 확장]

oop, js prototype 마찬가지로 기존의 interface를 확장해서 사용한다는 개념

interface Person2 {
    name: string
    age: number
}

// interface Developer {
//     name: string //중복
//     age: number //중복
//     language: string
// }

interface Developer extends Person2{
    language: string
}
  • extends 키워드를 사용
    확장을 하려고 할 때 이미 다른 인터페이스에 있는 속성이 중복될 경우에는
    갖고 있는 속성과 타입에 대해 상속을 받아서 사용할 수 있다.
const newPerson: Developer = {
    name: 'lili'
} //에러 발생

const newPerson: Developer = {
    name: 'lili',
    age: 33,
    language: 'ts'
}
  • 확장한 인터페이스로 객체를 선언
    만약 하나의 속성만 사용하게 되면 인터페이스 오류가 나게 된다.
    Person과 Developer의 타입들을 모두 정의 해줘야 하는것이 인터페이스 확장의 규칙이다.
profile
비니로그 쳌킨

0개의 댓글