타입 단언보다 타입 선언을 사용하기

이재철·2023년 4월 3일
0

TypeScript

목록 보기
4/11
post-thumbnail
post-custom-banner

타입 단언과 선언

타입스크립트에서는 변수에 값을 할당하고 타입을 부여하는 방법은 두가지입니다.

interface Person {name : string};
const alice : Person = {name : 'Alice'} //타입은 Person
const bob = {name : 'Bob'} as Person //타입은 Person
  1. 타입 선언 : alice:Person
  2. 타입 단언 : as Person

타입 단언보다 타입 선언을 사용하는 게 낫습니다.

const alice : Person = {
    name : 'Alice',
    occupation : 'TypeScript developer'
    // ~~~~ 개체 리터럴은 알려진 속성만 지정할 수 있으며
    // 'Person' 형식에 'occupation'이(가) 없습니다.
};
const bob = {
    name : 'Bob',
    occupation : 'JavaScript developer'
} as Person; // 오류 없음

타입 선언문에는 잉여 속성 체크 가 동작했지만, 단언문에는 적용되지 않습니다.

화살표 함수의 타입 선언은 추론된 타입이 모호할 때가 있습니다.

const people = ['alice', 'bob', 'jan'].map(name => ({name}));
// Person[]을 원했지만 결과는 {name : string;}[]...

타입 단언을 사용하면 문제가 해결되는 것처럼 보이지만, 런타임에 문제가 발생할 수 있습니다.

const people = ['alice', 'bob', 'jan'].map(name => ({name} as Person));
// 타입은 Person[]

// 런타임에서 문제가 발생할 수 있음
const people = ['alice', 'bob', 'jan'].map(name => ({} as Person));
// 오류없음

단언문을 사용하지 않고 화살표 함수 안에 타입과 함께 변수를 선언하는 것이 가장 직관적입니다.

const people = ['alice', 'bob', 'jan'].map(name => (
    const person:Person = {name};
    return person
)); // 타입은 Person[]

// 간결한 코드를 위해 변수 대신 화살표 함수의 반환 타입을 선언
const people = ['alice', 'bob', 'jan'].map(
    (name):Person => ({name})
); // 타입은 Person[]'

(name): Person 은 name에 타입이 없고 반환 타입이 Person 임을 명시합니다.

(name: Person) 은 name의 타입이 Person 임을 명시하고 반환 타입은 없기 때문에 오류가 발생합니다.

최종적으로 원하는 타입을 직접 명시하고, 타입스크립트가 할당문의 유효성 검사하게 합니다.

const people: Person[] = ['alice', 'bob', 'jan'].map(
    (name):Person => ({name})
); // 타입은 Person[]'

타입 단언이 꼭 필요한 경우

타입스크립트는 DOM에 접근할 수 없습니다.
자주쓰이는 특별한 문법(!)을 사용하여 null이 아님을 단언하는 경우도 있습니다.

const elNull = document.getElementById('foo'); //타입은 HTMLElement | null
const el = document.getElementById('foo'); //타입은 HTMLElement 
  • 변수의 접두사로 쓰인 !는 boolean의 부정문입니다.
  • 접미사로 쓰인 !는 그 값이 null이 아니라는 단언문으로 해석됩니다.

단언문은 컴파일 과정 중에 제거되므로, 타입 체커는 알지 못하지만 그 값이 null이 아니라고 확신할 수 있을때 사용해야 합니다.

타입 단언문으로 임의의 타입 간에 변환을 할 수는 없습니다.
A가 B의 부분집합인 경우에 타입 단언문을 사용해 변환할 수 있습니다.

➡ HTMLElement는 HTMLElement | null의 서브타입이기 때문에 이러한 타입 단언은 동작

interface Person { name: string; }
const body = document.body;
const el = body as Person;
// 형식이 충분히 겹치지 않기 때문에 실수로 판단, 의도적인 경우 먼저 식을 unknown으로 변환하세요.

const el = body as unknown as Person;
profile
혼신의 힘을 다하다 🤷‍♂️
post-custom-banner

0개의 댓글