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개의 댓글

관련 채용 정보