전체 글

개발자 린다씨
👶 TypeScript

정제

정제 TypeScript는 심벌 수행(symbolic execution)의 일종인 흐름 기반 타입 추론을 수행합니다. 즉, 타입 검사기는 typeof, instanceof, in 등의 타입 질의뿐 아니라, 마치 프로그래머가 코드를 읽듯 if, ?, ||, switch 같은 제어 흐름 문장까지 고려하여 타입을 정제(refinement)합니다. 이는 타입 검사기에 제공되는 아주 유용한 기능으로 오직 일부의 언어에서만 지원합니다. 예를 살펴보겠습니다. TypeScript에 CSS 규칙을 정의하는 내장 API가 있고 동료 개발자가 HTML 요소의 너비(width)를 설정하려 한다고 가정해 봅시다. 너비를 전달하면 이를 파싱하고 검증할 것입니다. 먼저 CSS 문자열을 값(value)과 단위(unit)로 파싱 하는..

👶 TypeScript

타입 넓히기 - 초과 프로퍼티 확인

초과 프로퍼티 TypeScript가 한 객체 타입을 다른 객체 타입에 할당할 수 있는지 확인할 때도 타입 넓히기를 이용합니다. 객체 타입과 그 멤버들은 공변 관계라는 규칙만을 적용하면 문제가 발생할 수 있습니다. 예를 들어 다음처럼 클래스에 전달해 그 내부 상태를 설정하는 용도의 Options라는 객체가 있다고 해보겠습니다. type Options = { baseURL: string cacheSize?: number tier?: 'prod' | 'dev' } class API { constructor(private options: Options){} } new API({ baseURL: 'https://cozy-linda.tistory.com', tier: 'prod' }) 옵션의 철자가 틀리면 어떤 일..

👶 TypeScript

타입 넓히기 - const 타입

타입 넓히기(type widening) 타입 넓히기는 TypeScript의 타입 추론이 어떻게 동작하는지 이해하는 데 필요한 핵심 개념입니다. TypeScript는 타입을 정밀하게 추론하기보다는 일반적으로 추론합니다. (덕분에 프로그래머의 삶이 편해집니다) let이나 var로 값을 바꿀 수 있는 변수를 선언하면 그 변수의 타입이 리터럴 값에서 리터럴 값이 속한 기본 타입으로 넓혀집니다. let a = 'x' // let a: string let b = 2 // let b: number var c = true // boolean const d = { x: 4} // (property) x: number enum E {A, B, C} let e = E.A // let e: E 값을 바꿀 수 없는 변수에선 상..

👶 TypeScript

할당성(assignability)

할당성(assignability) 서브 타입과 슈퍼 타입의 관계는 모든 정적 타입 언어에서 중요한 개념입니다. 또한 할당성(assignability)이 어떻게 동작하는지 이해하는데도 중요합니다. 할당성이란 A라는 타입을 다른 B라는 타입이 필요한 곳에 사용할 수 있는지를 결정하는 TypeScript 규칙을 의미합니다. "A를 B에 할당할 수 있는가?"라는 질문이 발생하면 TypeScript는 다음과 같은 몇 가지 규칙에 따라 처리합니다. 배열, 불(boolean), 숫자, 객체, 함수, 클래스, 클래스 인스턴스, 문자열, 리터럴 타입 등 열거형이 아닌 타입에선 다음의 규칙으로 A를 B에 할당할 수 있는지 결정합니다. A

👶 TypeScript

함수 가변성

함수 가변성 몇 가지 예를 살펴보겠습니다. 함수 A가 함수 B와 같거나 적은 수의 매개변수를 가지며 다음을 만족하면, A는 B의 서브 타입입니다. A의 this 타입을 따로 지정하지 않으면 'A의 this 타입 >: B의 this 타입'입니다. 'A의 각 매개변수 >: B의 대응 매개변수'입니다. 'A의 반환 타입 Flower' 형식의 인수는 '(r: Rose) => Rose' 형식의 매개 변수에 할당될 수 없습니다. // 'red' 속성이 'Flower' 형식에 없지만 'Rose' 형식에서 필수입니다.ts(2345) // index.ts(4, 3): 여기서는 'red'이(가) 선언됩니다. clone(roseToFlower) roseToThron은 정상 동작하지만 roseToFlower에서 에러가 발생합..

👶 TypeScript

형태와 배열 가변성

형태와 배열 가변성 복합 타입의 서브 타입 규칙은 왜 언어마다 다를까요? 이번 글에서 소개하는 복잡한 타입(형태)을 예로 살펴보겠습니다. 일단 응용 프로그램에 사용자를 묘사하는 형태가 있다고 가정하고, 다음처럼 두 가지 타입으로 표현한다고 해봅시다. // 서버로부터 받은 기존 회원 type ExistingMemer = { id: number nickName: string } // 아직 서버에 저장하지 않은 새 회원 type NewMember = { nickName: string } 어떤 동아리의 회원 관리를 하게 되었는데 회원을 삭제하는 코드를 구현하는 역할을 맡았으면 다음과 같이 구현할 수 있습니다. // 서버로부터 받은 기존 회원 type ExistingMemer = { id: number; nick..

👶 TypeScript

가변성

가변성 보통 A라는 타입이 V라는 다른 타입의 서브 타입인지 아닌지 쉽게 판단할 수 있습니다. number, string 등의 단순 타입은 위의 흐름도로 확인하거나 자체적으로 쉽게 추론할 수 있습니다. (예: number는 number | string 유니온에 포함되므로 number | string의 서브 타입입니다.) 매개변수화된(제네릭) 타입 등 복합 타입에선 이 문제가 더 복잡해집니다. 아래의 상황을 살펴보겠습니다. Array는 어떤 상황에서 Array의 서브 타입이 될까요? 형태 A는 어떤 상황에서 다른 형태 B의 서브 타입이 될까요? 함수 (a: A) => B는 어떤 상황에서 다른 함수 (c: C) => D의 서브 타입이 될까요? 다른 타입을 포함하는 타입(Array처럼 타입 매개변수를 갖거나,..

👶 TypeScript

서브 타입과 슈퍼 타입

서브 타입 두 개의 타입 A와 B가 있고 B가 A의 서브 타입이면 A가 필요한 곳에는 어디든 B를 안전하게 사용할 수 있습니다. TypeScript에 기본적으로 있는 서브 타입의 몇 가지 예는 아래와 같습니다. 배열은 객체의 서브 타입입니다. 튜플은 배열의 서브 타입입니다. 모든 것은 any의 서브 타입입니다. never는 모든 것의 서브 타입입니다. Animal을 상속받는 Dog 클래스가 있다면 Dog는 Animal의 서브 타입입니다. 서브 타입의 정의를 여기에 적용하면 다음과 같이 설명할 수 있습니다. 객체를 사용해야 하는 곳에 배열도 사용할 수 있습니다. 배열을 사용해야 하는 곳에 튜플도 사용할 수 있습니다. any를 사용해야 하는 곳에 객체도 사용할 수 있습니다. 어디에나 never를 사용할 수 ..

👶 TypeScript

디자인 패턴 - 빌더 패턴(builder pattern)

빌더 패턴(builder pattern) 빌더 패턴(builder pattern)으로 객체의 생성과 객체 구현 방식을 분리할 수 있습니다. 제이쿼리(JQuery)나 ES6의 Map, Set 등의 자료구조를 사용해 봤다면 빌더 패턴에 친숙할 것입니다. 빌더 패턴은 아래처럼 구성됩니다. new RequestBuilder() .setURL('/users') .setMethod('get') .setData({ firstName: 'Cozy'}) .send() RequestBuilder를 구현하는 방법은 간단합니다. 우선 클래스 뼈대를 정의합니다. class RequestBuilder{} 첫 번째로 .setURL 메서드를 추가합니다. class RequestBuilder{ private url: string | ..

개발자 린다씨
Cozy_Linda