Front-end/Typescript

Typescript typeof Array[number] 패턴 정리

아지송아지 2022. 6. 5. 10:58

안녕하세요!

오늘은 typeof Array[number]에 대하여 알아보겠습니다.

최근에 이직을 하고 정신이 없어서 블로그 글도 못 올리고 1일 1 깃도 못했네요.

 

 

typeof Array[number]?


const names = ["Song", "James", "Mike"] as const;
type Name = typeof names[number];

// type Name: "Song", "James", "Mike"

패턴은 위와 같이 생겼는데요.

Name 타입을 정의할 때 유니온 타입을 사용하여 Song, James, Mike를 중복해서 적지 않은 것을 확인할 수 있습니다. 

 

문제점과 패턴에 대해 자세히 살펴보겠습니다.

 

 

 

문제점


만약 이 방식을 사용하지 않으면 어떻게 될까요?

 

 

1. 타입을 정의하지 않는다.

const names = ["Song", "James", "Mike"];

// logName의 매개변수는 "Song", "James", "Mike" 셋 중 하나임을 가정
function logName(name: string){
    console.log(name);
}

logName('Song'); // o
logName('Tom'); // x

애초에 타입을 적지 않으면 인자가 예상했던 값과 다른 값이 올 수도 있습니다. 

 

 

 

2. 타입을 선언한다.

const names = ["Song", "James", "Mike"];
type Name = 'Song' | 'James' | 'Mike';

function getName(name: Name){
    return names.find(n => n===name)
}

logName('Song'); // o
logName('Tom'); // x

타입을 정의한다면 다른 값이 오는 것을 사전에 방지할 수 있습니다.

1번의 문제점은 해결하였지만 이름들이 중복해서 사용됐습니다. 옳지 않습니다.

지금은 세 개밖에 없어서 괜찮지만, 값이 늘어나면 불필요한 코드의 양도 늘어납니다.

 

 

 

패턴 분석


const names = ["Song", "James", "Mike"] as const

이 코드부터 알아보겠습니다.

 

const names = ["Song", "James", "Mike"];
// const names: string[]

먼저 as const를 사용하지 않은 names의 타입 string[]입니다.

 

저희는 초기에 선언된 값 이외에는 더 추가되지 않을 것이기 때문에 이것을 불변한 값으로 바꿔줘야 합니다.

string[] -> readonly ["Song", "James", "Mike"] 이렇게 말이죠

 

Const assertions

typescript 3.4 버전에서 추가된 기능인 Const assertions를 사용합니다.

선언한 변수들을 마치 const처럼 만들어 줍니다.

두 가지 예시를 들어보겠습니다.

 

const name = "Song";
// const name: "Song"

let name2 = "Song"
// let name2: string

let name3 = "Song" as const
// let name3: "Song"

const로 변수를 선언하면 타입은 "song"이지만 let으로 선언하면 string이 됩니다.

as const를 사용하면 let으로 선언하였어도 타입은 "song"이 됩니다.

 

const abcd = ["a", "b", "c", "d"];
// const abcd: string[]
abcd.push("e"); // o

const ABCD = ["A", "B", "C", "D"] as const;
// const ABCD: readonly ["A", "B", "C", "D"]
ABCD.push("E"); // Property 'push' does not exist on type 'readonly ["A", "B", "C", "D"]'

const로 선언한 객체는 객체 내부의 타입들이 넓은 범위의 타입으로 추론됩니다.

const assertion을 사용하면 그 범위를 좁혀줍니다. 

 

 

type Name = typeof names[number];
// type Name: "Song" | "James" | "Mike"

다음  코드를 살펴보겠습니다.

typeof names[number]를 사용하여 배열 안에 있는 숫자로 이루어진 모든 index 값을 가져와 유니온 타입으로 만들어줍니다. (index signature 문법)  이로 인하여 똑같은 값을 한번 더 사용하지 않고도 유니온 타입을 만들었습니다.

 

 

const people = [
  { age: 20, name: 'Song' },
  { age: 21, name: 'James' },
  { age: 22, name: 'Mike' }
] as const

type Name = typeof animals[number]['name']

배열 안에 오브젝트가 있을 경우 다음과 같이 사용하시면 됩니다.

 

 

 

참고 : https://steveholgado.com/typescript-types-from-arrays/

 

 

 

 

 

'Front-end > Typescript' 카테고리의 다른 글

Typescript Generic  (0) 2022.03.22
Typescript enum 정리  (0) 2022.02.28
Typescript 유니온, 인터섹션 타입  (0) 2022.02.28
Typescript type alias & interface  (0) 2022.02.24
Typescript에서 함수 선언하기  (0) 2022.02.22