언어/타입스크립트

[Typescript] 사용자정의 타입, 함수타입, unknown type, 절대타입

youngble 2022. 3. 12. 00:40

 

타입스크립트는 컴파일 과정에서 에러를 잡아내기 때문에, 기존에 런타임에서 발생하던 에러를 개발단계에서 핸들링 할 수 있게 된다.

(자바스크립트 사용시에는 런타임 환경에서 실행전까지는 에러 확인할 수 없는데..)

또한 생각해보면 새로운 개발자가 합류하거나 기존의 팀에서 코드수정을 하기위해서 코드를 볼때

타입이 결정되어있어서 코드리뷰를 할때 좀더 직관적으로 어떤 변수,함수 인지 정확히 알수있다는것이다.

만약 다른사람이 잘못쓰더래도 바로 컴파일에러로 보여주기때문에 코드 수정이나 fix 하기가 자바스크립트보다 훨씬 좋다는것이다.

사용자정의 타입

사용자가 임의로 타입을 변수에 담아 만들어놀수있다.

type Combinable = number | string;
type num = number;
type str = string;
type ConversionDescriptor = "as-number" | "as-text";

타입 별칭을 사용하여 타입을 직접 “생성”할 수 있습니다. 유니온 타입을 저장하는 것만 가능한 것이 아닙니다. 복잡할 수 있는 객체 타입에도 별칭을 붙일 수 있습니다.

type User = { name: string; age: number };
const u1: User = { name: 'Max', age: 30 }; // this works!

함수타입 정의

let CombineValues : Function

이렇게 정의 할수있는데 이렇게 하면

CombineValues 에 함수 를 넣을수있다. 하지만 만약 인자 갯수가 다르거나 타입이 달를때 분별해서 넣어야하는데 이렇게하면 모든 함수를 넣을수 있기 때문에 화살표 함수를 사용해서 좀더 명확히 함수타입을 정의할수있다

let CombineValues : (n1: number, n2: number) ⇒ number;

이런식으로 함수를 인자 갯수, 타입, 반환값을 결정할수있다.

콜백함수

함수 선언할때 콜백함수를 넣을수도 있음

function addAndHandle(n1: number, n2: number, cb: (num: number) => void) { const result = n1 + n2; cb(result); }
addAndHandle(10,20,(result)=>{ console.log(result) })
function sendRequest(data: string, cb: (response: any) => void) { // ... sending a request with "data" return cb({data: "Success"}); }
sendRequest('Send this!', (response) => { console.log(response); return true; });

→이거같은경우는 return 이 cd({data:”Success”}) 이므로 ‘Send this!’ 라고 data 인자에 넣어도 sendRequest 함수의 첫번째 인자 data와 콜백함수의 response key인 data와 같은게 아니기때문에 Success만 출력한다.

unknown type 알수없는 타입

타입이 결정되어있지 않을때 사용하는데 any 와 다른점이 있나?

let useInput : unknown;
useInput="ma";
useInput=2;

→ 정해져있지 않기때문에 string값을 넣고 number값을 넣어도 에러없이 잘됨

any 와 차이

any와 차이는 이렇게 정의한 useInput을 만약에 다른 변수에 넣어줄때 에러가 뜬다.

unknown 을 any로 바꿔주면 에러가 사라진다.

따라서 unknown 은 any 보다 좀더 제한적이다.

만약 unknown을 쓰면서 userName 변수에 넣어주고싶다면 if 문으로 타입체크를 해야한다.

let useInput : unknown;
let userName : string;
useInput="ma";
if(typeof useInput === 'string'){
userName= useInput;
}

→ 이러면 에러가없다. 따라서 any보다 이런점이 더 좋은것이다. 처음에는 어떤값이 들어갈지 알수없기때문에 unknown을 하고 만약 내가 넣어주고싶은 값이 string이나 number, object 등등으로 제한이 될때 if문을 써서 제한을 걸수있지만 any일경우는 모든 타입을 쓸수있기때문에 unknown을 쓰면 타입에 대한 정의를 좀더 명확하게 에러를 통해 볼수있다. 당연히 any 일때도 if문을 쓸수 있지 않냐고 생각할수있지만 당연히 쓸수있다. 하지만 쓰기전에 개발자가 if문을 만들기전에 에러를 통해 체크할려면 계속해서 까먹지 않고 알고있거나 다른 협업하는사람이 있다면 이거를 상기하고 코드를 작성해야한다. 따라서 if문을 써서 대입을 하건 안하건을 떠나서 협업 이나 자유도를 인간으로써 미리 체크하기위해선 unknown을 쓰는게 처음엔 어떤 타입인지 정하지않고 넣고도 나중에 그 값이 string이건 number에 따라 원치않은 타입일때는 더 제한적으로 체크하고 쓸수있다는것이다.

만약 위의 useInput 타입이 항상 string이나 number 이라는걸 안다면 유니온 타입으로 써도 된다.

절대타입 Never type (absolute와 헷갈리면 안된다)

보통 throw를 통해 에러메세지를 보내고싶을때 에러 함수를 만드는데

function ErrorMessage(message: string, code: number) {
throw { message: message, errorCode: code };
}
ErrorMessage('this is Error test',500);

이렇게 작성하면 에러코드로 ‘this is Error test’ 와 500 이 같이 콘솔창에 뜬다.

이때 ErrorMessage라는 함수의 반환 타입이 없는데 아무것도 안써도 void 또는 never로 지정된다. throw를 사용할경우 그 자체가 에러를 내보내기때문에 스크립트와 충돌한다 따라서 절대로 아무값도 반환하지않는다.

예를들어 throw가 에러메세지를 반환한다고 생각해서

const testError = ErrorMessage(’this is Error test’, 500);
console.log(testError);

라고써도 콘솔로그가 뜨지않는다 왜냐하면 저거 자체가 에러이므로 스크립트와 충돌로 스크립트가 취소된다.