TypeScript - chapter11 / 러닝 타입스크립트

조용환·2024년 5월 1일
0

TypeScript

목록 보기
2/3

선언 파일

타입스크립트는 구현과 별도로 타입 형태를 선언할 수 있음.
타입 선언은 파일 이름이 .d.ts 확장자로 끝나는 선언 파일에 작성됩니다.

선언 파일

.d.ts 선언 파일은 런타임 코드 포함 불가 하다는 제약 사항 외에는 거의 .ts와 같음
ex) 사용법

// types.d.ts
export interface Character {
  catchphrase?: string;
  name: string;
}
// index.ts
import {Character} from "./types";

export const character: Character = {
  catchphrase: "Yee-haw!",
  nae: "Sandy cheeks",

선언 파일은 값이 아닌 타입만 선언할 수 있는 코드 영역을 의미하는 앰비언트 컨텍스트를 생성합니다.
앰비언트 컨텍스트 : 자바스크립트에서 일반적으로 사용되는 실행 컨텍스트의 하위 개념

런타임 값 선언

선언 파일은 함수 또는 변수 같은 런타임 값 생성 x 이지만, declare 키워드를 사용해 이러한 구조체가 존재한다고 선언할 수 있음
초기값 허용되지 않는다는 점 제외 일반적인 변수 선언과 동일한 구문

// ex)
// types.d.ts
declare let declared: string; //OK

declare let initializer: string ="Wanda";
//Error : initializers are not allowed in abient contexts.

함수와 클래스도 비슷하지만 본문이 없음.

declare 키워드를 사용한 타입 선언은 .d.ts 선언 파일에서 사용하는 게 가장 일반적 하지만 선언 파일 외부에서도 사용 가능
전역으로 사용가능한 변수가 해당 파일에서만 사용되어야 하는 경우 declare 키워드가 유용.

전역 변수

import 또는 export 문이 없는 타입스크립트 파일은 모듈이 아닌 스크립트로 취급.따라서 이를 이용해 타입을 전역으로 선언할 수 있음
다음 globals.d.ts는 전역으로 존재하는 const version: string을 선언.

// globals.d.ts
declare const version: string;
//version.ts
export function logVersion() {
  console.log('Version: ${version}');
}

전역 인터페이스 병합

변수는 유일한 전역은 아니며 전역 API와 값에 대한 많은 타입 선언이 전역으로 존재. 인터페이스는 동일한 이름의 다른 인터페이스와 병합되기 때문에 import와 export 문이 없는 .d.ts 선언 파일 같은 전역 스크립트 컨텍스트에서 인터페이스를 선언하면 해당 인터페이스가 전역으로 확장됨.

// File1.ts
interface Car {
    brand: string;
}

// File2.ts
interface Car {
    model: string;
}

// Main.ts
const myCar: Car = {
    brand: "Toyota",
    model: "Camry"
};

전역 확장

declare global 코드 블록 구문을 사용해 해당 블록 내용이 전역 컨텍스트에 있다고 표시.

내장된 선언

Array, Function, Map, Set과 같은 전역 객체는 타입 시스템이 알아야 하지만 코드에서 선언되지 않는 구문. 이와 같은 전역 객체는 디노, Node.js, 웹 브라우저 등에서 실행되는 런타임 코드에 의해 제공

라이브러리 선언

Array, Function 같은 내장된 전역 객체는 lib, [target].d.ts 파일 이름으로 선언.

라이브러리 target

타입스크립트는 기본적으로 tsc CLI 또는 프로젝트의 tsconfig.json(기본값은 (es5)에서 제공된 target 설정에 따라 적절한 lib 파일을 포함 인터페이스 병합을 사용해 서로 빌드.

DOM 선언

DOM 타입이라고 하는 웹 브라우저 타입은 local Storage와 같은 API와 웹 브라우저에서 주로 사용하는 HTMLElement와 같은 타입 형태를 다룸. DOM 타입은 lib.dom.d.ts 파일과 다른 lib.*.d.ts 선언 파일에도 저장

lib 컴파일러 옵션을 재정위하지 않는 타입스크립트 프로젝트는 DOM 타입을 기본으로 포함.
Node.js와 같은 브라우저가 아닌 환경에서 실행되는 프로젝트는 타입 시스템이 존재한다고 주장하는 document와 localStorage 같은 전역 API에 접근할 수 없기 때문에 개발자가 혼란스러울 수 있음.

모듈 선언

선언 파일의 또 다른 중요한 기능은 모듈의 상태를 설명하는 기능.
모듈 문자열 이름 앞에 declare 시 모듈 내용을 타입 시스템에 알릴 수 있음.

// module.d.ts
declare module "my-example-lib" {
  export const value: string;
}
// index.ts
import {value } from "my-example-lib";

console.log(value);

코드에서 declare module을 자주 사용하면 안됨. 와일드 카드 모듈 선언 or 후반부 다루는 패키지 타입과 함께 사용함.

와일드카드 모듈 선언

모듈 선언은 js와 ts 파일 확장자가 아닌 특정 파일의 내용을 코드로 가져올 수 있음을 웹 애플리케이션에 알리기 위해 사용. 모듈 선언으로 하나의 * 와일드카드를 포함해 해당 패턴과 일치하는 모든 모듈을 나타낼 수 있음.

CSS 모듈을 지원하면 CSS 파일에서 런타임에 사용할 수 있는 객체로 스타일을 가져옴.
기본적으로 { [i: string]: string } 타입의 객체를 내보내는 "*.module.css"와 같은 패턴으로 모듈을 정의함.

// styles.d.ts
declare module "*.module.css" {
  const styles: { [i: string]: string} ;
  export default styles;
}
import styles from "./styles.module.css";

styles.anyClassName; // 타입 : string
  • 와일드카드 모듈을 사용해 로컬 파일을 나타내는 방식이 타입 안정성을 완벽히 보장하지는 않음. 일부 프로젝트는 웹팩 같은 빌드 시스템을 사용하거나 로컬 파일에서 .d.ts 파일을 생성해 가져오기가 가능한지 확인합니다.

패키지 타입

선언

ts는 입력된 파일에 대한 .d.ts 출력 파일과 js 출력 파일을 함께 생성하는 옵션을 제공함.
다음 index.ts 소스 파일이 주어졌다고 가정해보자.

// index.ts
export const greet = ( text: string) => {
  console.log("Hello, ${text}!");
};

module은 es2015, target은 es2015인 선언 옵션을 사용해 다음 출력 파일을 생성

// index.d.ts
export declare const greet: (text:string) => void;
//index.js
export const greet = (text) => {
  console.log('Hello, ${text}!');
};

자동으로 생성된 .d.ts파일은 프로젝트에서 사용자가 사용할 타입 정의를 생성하는 가장 좋은 방법.

패키지 타입 의존성

자체 .d.ts 선언 파일고 함께 제공되는 npm 모듈은 대부분 다음과 같은 파일 구조를 가짐.

lib/
	index.js
    index.d.ts
package.json

예를 들어 꾸준히 인기 있는 테스트 프레임워크인 제스트는 타입스크립트로 작성되었으며 jest 패키지 내에 자체 번들 .d.ts 파일을 제공함. describe와 it 같은 함수를 제공하는 @jest/globals 패키지에 대한 의존성을 가지며 jest는 전역으로 사용할 수 있음.

// package.json
{
	"devDependencies": {
    	"jest": "^32.1.0"
    }
}
// using-globals.d.ts
describe("MyAPI", () => {
	it("works", () => { /* ... */ });
});
//using-imported.d.ts
import {describe, it} from "@jest/globals";

describe("MyAPI", () => {
	it("works", () => { /* ... */});
});

패키지 타입 노출

프로젝트가 npm에 배포되고 사용자를 위한 타입을 제공하려면 패키지의 package.json 파일에 types 필드를 추가해 루트 선언 파일을 가리킵니다. types 필드는 main 필드와 유사하게 작동하고 종종 동일한 것처럼 보이지만, .js 확장자 대신에 .d.ts 확장자를 사용함.

예를 들어 다음 가상의 package 파일에서 main 런타임 파일인 ./lib/index.js는 types 파일인 ./lib/index.d.ts와 병렬 처리됨.

{
	"author" : "Pendant Publishing",
    "main" : "./lib/index.js",
    "name" : "coffeetable",
    "types" : "./lib/index.d.ts",
    "version": "0.5.22",
}

그런 다음 타입스크립트는 유틸리지 패키지에서 가져온 파일을 사용하기 위해 제공해야 하는 것으로 ./lib/index.d.ts의 내용을 사용함.

  • 타입 필드가 패키지의 package.json에 존재하지 않으면 타입스크립트는 ./index.d.ts를 기본값으로 가정함.

DefinitelyTyped

  • TS 프로젝트는 여전히 해당 패키지에서 모듈의 타입 형태를 알려줘야 함.
  • 타입스크립트 팀과 커뮤니티는 커뮤니티에서 작성된 패키지 정의를 수용하기 위해 DefinitelyTyped 라는 거대한 저장소를 만들었음. 짧게줄여서 DT는 깃허브에서 가장 활발한 저장소 중 하나. 저장소에는 변경 제안 검토 밑 업데이트 게시와 관련된 자동화 부분과 수천 개의 .d.ts 정의 패키지가 포함되어 있음.
  • DT 패키지는 타입을 제공하는 패키지와 동일한 이름으로 npm에 @types 범위로 게시됨.
    예를 들어 2022년 집필 시점 @types/react는 리액트 패키지에 대한 타입 정의를 제공함.

시멘틱 버저닝인 "semver" 번호는 @types/ 패키지와 패키지가 나타내는 패키지가 서로 반드시 일치하지는 않음. 초기의 리액트 같은 패치 버전, 심지어 메이저 버전에서 일치하지 않는 부분을 종종 발견가능.

WARING : 커뮤니티에서 작성되기 때문에 상위 프로젝트보다 뒤쳐지거나 약간 부정확할 수 있음. 프로젝트가 성공적으로 컴파일되었지만 라이브러리 호출 시 런타임 오류 발생하면 접근하고 있는 API의 서명이 변경되었는지 확인할 것.

타입 사용 가능성

아직 사용 가능한 타입이 없는 패지키에서 타입을 얻는 일반적인 세 가지 옵션은 다음과 같음

  • @types/ 패키지를 생성하기 위해 DefniteTyped에 풀 리퀘를 보내기.
  • declare module 구문을 사용해 프로젝트 내에서 타입 작성
  • 13장 구성 옵션에서 다루게 될 noImplicitAny 옵션을 비활성하고 강력하게 경고

시간이 있다면 DT에 타입을 제공하는 것이 좋음.

profile
practice react, javascript

0개의 댓글