본문 바로가기

Frontend/Typescript

타입 조작하기

타입 조작하기

타입 조작하기는 기본 타입이나 별칭 또는 인터페이스로 만든 원래 존재하던 여러 가지 타입들을 타입스크립트의 특수한 문법을 이용해서 상황에 따라 다른 타입으로 변환하는 기능이다.

제네릭도 그런 관점에서 타입 조작하기에 속한다.

 

이제부터 타입 조작하기에 속하는 것들을 자세히 알아보자.

 

인덱스드 액세스 타입

인덱스드 액세스 타입은 객체, 배열, 튜플 타입에서 특정 프로퍼티/요소의 타입을 추출하는 타입인데, 아래 코드에서 세 경우를 모두 확인해볼 수 있다.

/**
 * 인덱스드 액세스 타입
 */

interface Post {
    title: string;
    content: string;
    author: {
        id: number;
        name: string;
    }
}

function printAuthorInfo(author: Post['author']['name']) {
    console.log(`${author}`);
}

const post: Post = {
    title: '',
    content: '',
    author: {
        id: 1,
        name: '이정환'
    }
};
type PostList = {
    title: string;
    content: string;
    author: {
        id: number;
        name: string;
    }
}[];

function printAuthorInfo(author: PostList[number]['author']) {
    console.log(`${author.name}-${author.id}`);
}

const post: PostList[number] = {
    title: '',
    content: '',
    author: {
        id: 1,
        name: '이정환'
    }
};
type Tup = [number, string, boolean];

type Tup0 = Tup[0];

type Tup1 = Tup[1];

type Tup2 = Tup[2];

type TupNum = Tup[number];  // string | number | boolean 타입

첫 번째 예는 객체와, 두 번째 예는 배열과, 세 번째 예는 튜플과 함께 사용한 예이다.

[] 안에 들어가는 문자열은 값이 아니라 타입이다.

따라서, 값을 넣지 않도록 주의해서 사용해야 한다.

 

keyof 연산자

keyof 연산자는 특정 객체 타입으로부터 프로퍼티 키들을 모두 스트링 리터럴 유니온 타입으로 추출하는 연산자이다.

아래 코드를 통해 알아보자.

/**
 * keyof 연산자
 */

interface Person {
    name: string;
    age: number;
}

function getPropertyKey(person: Person, key: keyof Person) {
    return person[key];
}

const person: Person = {
    name: '이정환',
    age: 27
}

getPropertyKey(person, 'name');

keyof 연산자를 사용하면 위 예에서는 “name” | “age”와 같은 결과가 나온다.

keyof 연산자는 타입에만 사용할 수 있는 연산자이기 때문에 주의해야 한다.

/**
 * keyof 연산자
 */

type Person = typeof person;  // type Person = {
                              //    name: string;
                              //    age: number;
                              // }

function getPropertyKey(person: Person, key: keyof typeof person) {
    return person[key];
}

const person = {
    name: '이정환',
    age: 27
}

getPropertyKey(person, 'name');

그리고 typeof 연산자는 위와 같이 어떤 변수의 타입을 뽑아내는 데 사용할 수 있다.

 

맵드 타입

맵드 타입은 기존의 객체 타입으로부터 새로운 객체 타입을 만드는 타입이다.

맵드 타입을 활용해서 유틸리티 타입을 많이 만든다.

이는 다음 글에서 알아보도록 하자.

/**
 * 맵드 타입
 */

interface User {
    id: number;
    name: string;
    age: number;
}

type PartialUser = {
    [key in keyof User]?: User[key];
}

type BooleanUser = {
    [key in keyof User]: boolean;
}

type ReadonlyUser = {
    readonly [key in keyof User]: User[key];
}

function fetchUser(): ReadonlyUser {
    return {
        id: 1,
        name: '이정환',
        age: 27
    }
}

function updateUser(user: PartialUser) {
    // 수정하는 기능
}

updateUser({
    age: 25
});

맵드 타입은 인터페이스에서는 만들 수 없다.

따라서 타입 별칭으로만 사용해야 한다.

 

템플릿 리터럴 타입

템플릿 리터럴 타입은 스트링 리터럴 타입을 기반으로 정해진 패턴의 문자열만 포함하는 타입이다.

잘 사용하지는 않지만, 그냥 알아두기만 하자.

/**
 * 템플릿 리터럴 타입
 */

type Color = 'red' | 'black' | 'green';

type Animal = 'dog' | 'cat' | 'chicken';

type ColoredAnimal = `${Color}-${Animal}`;

// type ColoredAnimal = "red-dog" | "red-cat" | "red-chicken" | "black-dog" | "black-cat" | "black-chicken" | "green-dog" | "green-cat" | "green-chicken"

'Frontend > Typescript' 카테고리의 다른 글

[이펙티브 타입스크립트] 타입을 명확하고 일관성 있게 써보자  (1) 2023.10.09
조건부 타입과 유틸리티 타입  (0) 2023.06.23
제네릭  (0) 2023.06.20
인터페이스와 클래스  (0) 2023.06.20
함수와 타입  (0) 2023.06.20