특수한 타입으로 볼 수 있는 세가지 타입에 대해 이야기한다.
Union은 여러개의 타입 중 하나가 들어갈 수 있는 것(or 개념)
any는 js처럼 모든 타입을 허용한다. 연산 등에서도 에러를 뱉지 않기 때문에 사실상 ts를 사용하는 의미를 상실한다.
unknown은 any와 용도가 비슷하지만 몇가지 상황에 대해 타입 체크를 하여 연산 등을 허용하지 않아 더 안전하다. any를 사용해야 한다면 unknown으로 하자.
예제는 아래
// 여러가지를 쓸 수 있는 유니온타입
type Union = (string | number | boolean)[]
let members: Union = [1,2,3,'lim',true];
// 아무거나 다 되는 애니타입
// 타입스크립트의 의미가 없어진다.
let ay: any;
ay = 'sdf';
ay = 234; // 다 가능
// 애니랑 비슷한 언노운 타입
// any랑 용도는 비슷하지만 더 안전하다.
let un: unknown;
un = 234;
un = 'swneif';
// 언노운이 더 안전한 이유1
// let variable1: string = un; // un은 unknown이므로 에러
// let variable2: string = ay; // ay는 any라 에러 안남
// 언노운이 더 안전한 이유2
// 숫자 연산 등을 막아준다.
// un - 1; // 에러
// ay - 1; // 에러 안남
// 타입스크립트는 연산에 엄격함
let age1 : string | number;
// age1 + 1; // 에러남. 유니온타입은 새로운 타입을 만들어내는 것이므로, +1 연산이 없기 때문.
let age2 : unknown = 1;
// age2 - 1; // 에러남. unknown은 숫자 연산 불가능
기본적으로 ts로 코드를 작성할 때, 안전을 위하여 Narrowing이나 Type Assertion의 규칙을 적용하여 작성한다는 듯하다. 내용을 살펴보면 각각은 아래와 같다.
Narrowing : typeof, in, instanceOf 등으로 파라미터의 타입을 체크해가며 로직을 작성한다.
Assertion : as 혹은 !를 붙여 타입을 검사해가며 로직을 작성한다.
두 가지 모두 kotlin에서 사용되는 개념이고 사용 방법도 동일하기 때문에 익숙한 문법이긴하나, 경험상 Assertion은 정말 확실한 것에만 잘 써야 한다. 그렇지 않으면 오히려 에러를 뿜을 수가 있다.
Narrowing은 참... 귀찮다 귀찮아. 차라리 typescript를 더 엄격하게 해서 java나 kotlin처럼 만드는게 나을 것도 같다.
예제는 아래와 같다.
// Narrowing
// number 타입을 보고 특정한 타입으로 보는 것
function padLeft(padding: number | string, input: string) {
// type이 number인 경우만 아래 분기를 태운다.
if (typeof padding === "number") {
return new Array(padding + 1).join(" ") + input;
}
return padding + input;
}
// Assertion
const getArea2 = (shape: Shape) => {
if (shape.kind === 'circle') {
// shape.radious가 비어있는 값이면 에러가 날 것이다. !는 값이 확실하게 있을 때 사용한다.
return Math.PI * shape.radious! ** 2;
}
// as를 통해 값의 타입을 확정한다. 타입변환이 안되는 값이 들어있었다면 에러가 날 것이다.
if (shape.kind as square === 'square') {
return shape.sideLength! ** 2;
}
return null;
}
// 아래와 같은 방법으로 사용도 가능하다
type NewType = {
id: string,
count: number
}
function convertNewType<T>(param: { id: string, count: number }): T {
return JSON.parse(param) as T;
}
const value = convertNewType<NewType>({id: "id", count: 5});
자세한 내용은 아래 블로그를 참조. 두 가지 개념 모두 설명하고 있다. 바로 위 예제 코드도 아래 블로그에서 일부 발췌하였다.
https://velog.io/@devstefancho/typescript-Narrowing
댓글