230616.til

Universe·2023년 6월 17일
0

타입스크립트 선언 파일(d.ts)

.d.ts 파일은 JS 모듈을 TS에서도 사용할 수 있도록 타입만을 선언한 파일

d.ts 파일, 선언 파일은 타입을 정의(declare) 하기 위해서 사용되는 파일이다.
선언 파일에는 함수, 클래스, 객체 리터럴의 인터페이스, 네임 스페이스, 모듈 등,
해당 프로젝트의 타양한 요소에 대한 타입 정보가 포함된다.
타입스크립트는 이러한 정보를 바탕으로 해당 자바스크립트 프로젝트의 API 와 구조를 이해할 수 있고,
타입 검사와 자동 완성 기능을 제공할 수 있게 도와준다.

쉽게 예를 들면, 과거에 자바스크립트를 이용해 만들어진 라이브러리 같은 경우,
타입스크립트 프로젝트에서 사용하려고 하면 타입에 대한 정보가 없으므로 사용할 수 없다.
이러한 경우에 d.ts 파일에 해당 자바스크립트 프로젝트의 타입을 제공하는 것으로 해결할 수 있다.
최근에는 DefinitelyTyped 같은 공용 레포지토리에 많은 개발자들이 이미 선언 파일을 공유하고 있어
npm 에서 @types/라이브러리 패키지로 제공된다.
멋진사람들이다.

주의해야 할 점이라면 d.ts 파일은 순수하게 type definition 만을 위한 파일이기 때문에,
type alias, interface 와 같은 타입의 정의 만 가능하다.

실습해보기 좋은 링크 : https://spookyjelly.tistory.com/83

Index Signature

Javascript 에서 객체 내부에 접근할 때 문자열을 이용한 접근이 가능하다.

let obj = {
	a: "soo"
}

console.log(obj['a']) // soo

이를 자바스크립트의 객체의 특정 value 에 접근할 때 그 value의 key 를 문자열로 인덱싱해 참조한다고 하여
Index Signature 라고 한다.

자바스크립트의 이러한 index signature 에 특정 객체가 동적으로 속성을 가질 수 있도록
타입을 지정해 줄 수 있다.
객체에 속성을 동적으로 추가할 때, 혹은 객체에 어떤 프로퍼티들이 있는지 명확히 알 수 없을 때 사용한다.
조금 더 쉽게 설명하자면 키와 값의 유형만 알고있는 어떤 객체의 구조에 대한 타입을 명시해준다. 라는 느낌.

아래의 예시를 보면 조금 더 명확한 쓰임새를 알 수 있다.

const salary1 = {
  baseSalary: 100_000,
  yearlyBonus: 20_000
};

const salary2 = {
  contractSalary: 110_000
};

function totalSalary(salaryObject: ???) {
  let total = 0;
  for (const name in salaryObject) {
    total += salaryObject[name];
  }
  return total;
}

console.log(totalSalary(salary1)); // => 120_000
console.log(totalSalary(salary2)); // => 110_000

위의 함수 totalSalary 는 salaryObject 라는 파라미터를 받을 것을 기대하고 있지만
salary 객체는 키와 값의 유형만 알고있을 뿐, 내부 구조를 명확하게 알 수 없다.
이런 경우,

function totalSalary(salaryObject: { [key: string]: number }) {
  let total = 0;
  for (const name in salaryObject) {
    total += salaryObject[name];
  }
  return total;
}

[key: string]: number 의 형태로 index signature 의 타입을 정의해주면 좋다.
위의 함수는 문자열을 value 로 갖는 객체는 인자로 넣을 수 없다.

const salary3 = {
  ins: "123123"
}

function totalSalary(salaryObject: { [x: string]: number; }) {
  let total = 0;
  for (const name in salaryObject) {
    total += salaryObject[name];
  }
  return total;
}

totalSalary(salary3) // '{ ins: string; }' 형식의 인수는 '{ [x: string]: number; }' 형식의 매개 변수에 할당될 수 없습니다.  'ins' 속성이 인덱스 시그니처와 호환되지 않습니다. 'string' 형식은 'number' 형식에 할당할 수 없습니다.

Index Signature 의 문제점

  1. 존재하지 않는 속성에 접근하더라도 에러로 취급하지 않음.
type IndexStringObj = {
  [key: string]: string;
}

const obj: IndexStringObj = {}

const value = obj['nothing']
console.log(value) // undefined
  1. key 에 string 타입을 할당했음에도 number 로도 접근할 수 있음.
type IndexNumber = {
  [key: string]: string;
}

const obj: IndexNumber = {
  '1' : 'one',
  '2':'two',
  '3':'three'
}

const value1 = obj[1];
const value2 = obj["1"]

console.log(value1, value2) // one one

Javascript는 객체의 속성에 접근 할 때 암시적으로 숫자를 문자열로 변환하게 되는데
타입스크립트에서도 이 강제변환을 수행한다.
하지만 이는 개발자의 의도와 맞지 않을 수 있기 때문에 주의.

  1. 너무 유연하기 때문에 생기는 문제.
type IndexStringObj = {
	[index: string]: string
}

위의 타입 엘리어스는 그 어떤 문자열도 key 값으로 가질 수 있다.
이렇게 의도를 했다면 상관없지만 사실상 모든 키를 허용하는 것은 의도하지 않은 속성이 추가되거나
잘못되 속성 이름을 사용하는 “휴먼에러”의 가능성이 있다.

type IndexStringObj = {
	[index: string]: string;
	id: string;
	name: string;
}

그런 경우에는 필요한 key 값을 타입 엘리어스에 미리 지정해주는 것으로 해결할 수 있다.

유틸리티 타입

참고할만한 링크
: https://typescript-kr.github.io/pages/utility-types.html
: https://inpa.tistory.com/entry/TS-📘-타입스크립트-유틸리티-타입-💯-총정리

Mapped Type

자바스크립트에는 Array.map 이라는 메소드가 있다.
각 배열의 요소에 대해 어떤 함수를 호출하여 그 리턴을 새 배열로 생성하는 역할을 한다.

const numArr = [1,2,3,4]
const squareArr = numArr.map(e=>e**2)

타입스크립트의 Mapped Type 은 map 메소드와 유사하게 해당 객체 속성을 순회하면서
다른 타입으로 바꿔주는 역할을 한다. 사실 for in 과 조금 더 유사하다고 볼 수 있다.
기본적인 사용법은 다음과 같다.

type MappedType = {
    [K in Keys]: Type
};

기존에 이런식의 타입을

type Man = {
  name: string;
  age: number;
}

type ReadOnlyMan = {
  readonly name: string;
  readonly age: number;
}

type PartialMan = {
  name?: string;
  age?: number;
}

이런식으로 간소화 할 수 있다.

type ReadOnly<T> = {
  readonly [P in keyof T]: T[P]
}

type Partial<T> = {
  [P in keyof T]?: T[P]
}

Type ReadOnlyMan = ReadOnly<Man>
Type PartialMan = Partial<Man>

제네릭과 같이 사용하면 재사용이 가능하다는 측면에서 유용하다.

profile
Always, we are friend 🧡

0개의 댓글