본문 바로가기

Frontend/JavaScript

2022-05-16:: [TypeScript]타입을 하고싶어요...

타입은 튜링 완전하다

타입스크립트의 타입 시스템은 튜링 완전하다.

튜링완전성
어떤 프로그래밍 언어나 추상 기계가 튜링 기계와 동일한 계산 능력을 가진다는 의미이다. 이것은 튜링 기계로 풀 수 있는 문제, 즉 계산적인 문제를 그 프로그래밍 언어나 추상 기계로 풀 수 있다는 의미이다

말이 어렵지 그냥 타입스크립트의 타입 시스템 만으로도 프로그래밍이 가능할 정도로 고수준이라는 뜻이다.

타입스크립트는 런타임이 아닌 타입 시간에 평가(evalueate)되는 코드이다.

타입시간
IDE에서 타이핑 하는 시간이다. IDE를 통해서 일종의 REPL을 수행한다.
P는 커서 위에 나타나는 콤보박스이다.
REPL
Read, Evaluate, Print, Loop의 약자이다. python이나 node.js의 shell모드를 의미한다.
shell 모드에 진입하면,
   1. 사용자의 입력을 읽고
   2. 입력받은 statement를 평가하고
   3. 평가한 결과를 출력하고
   4. 사용자가 종료하기 전까지 반복한다

타입 시스템

타입 스크립트의 타입 시스템은 작은 순수 함수형 언어이다.

타입 시스템이 할 수 있는 것들

  • 함수
  • 조건 분기 - Conditional Branching
  • 변수 대입
  • 반복 - Loops
  • 동일성 체크

타입 시스템이 할 수 있는 것들

  • 상태 변경 - Mutable state
  • 파일 입출력 - I/O
  • 고계도 함수 - HOC

공리계

공리 Axiom
어떤 한 형식체계에 관한 논의를 위한 전제로 주어진 공리들의 집합을 공리계라고 부른다

타입 시스템을 이루는 공리 즉 기본적인 전제에는 무엇이 있을까?

1. 타입은 집합이다.

  • 타입레벨에서 우리가 항상 다루는 것은 집합이다.
  • number, string은 무한 집합이다
  • A | B는 A와 B의 합집합이다.
  • A & B는 A와 B의 교집합이다.
  • unkown은 모든 집합의 상위집합(superset)이다.
  • never은 모든집합의 부분집합(subset)이다.
  • any는 모든 타입의 부분집합이자 상위집합이다.

2. 타입으로 데이터를 표현한다.

  • 다른 언어처럼 값을 가질 수 있다. 하지만 이 값들은 모두 타입이다.
  • 원시 자료형 - e.g. number, boolean, string, ... 
  • 리터럴 - e.g. 20, 15, true, false, "asdf", "hello", ... 
  • 자료구조 - e.g. {key: "value"}, [1, 2, 3], number[]

함수

타입 시스템의 함수는 제너릭이다

type F<A, B> = A | B
  • 함수명: F
  • 인자: A, B
  • 리턴: A | B

분기

type IF < A extends boolean, B, C> =
	A extends true ? B : C
    
type val1 = IF<true, number, boolean> // val1: number
type val2 = IF<false, number, boolean> // val2: boolean
  • 삼항 연산자로 분기를 구현할 수 있다

extends의 두 가지 사용법

1. 제한 Constraint

type IF<A extends boolean, B, C>

 

  • A는 무한집합 boolean의 부분집합으로 제한된다.
  • A에 boolean 아닌 타입이 온다면 IDE는 오류로 판단한다.

2. 판단

  A extends true ? B : C
  • A가 리터럴 타입 true의 부분집합인가를 판별
  • 참이라면 B로 분기
  • 거짓이라면 C로 분기
  • 리스코프 치환원칙
리스코프 치환원칙
자료형의 의미론적 처리를 보장하기 위한 법칙이다.
A extends B일 때, B를 A로 대체해도 문제가 없어야 한다.
OOP의 상속, 다형성과 연관된 개념이다.

infer

infer 키워드는 Generic을 위한 Generic이다.

인자로 리스트를 받아 길이를 반환하는 함수 LengthOf<T>를 어떻게 구현할 수 있을까?

type LengthOf<T extends { length: unknown }> =
	T extends { length: infer R } ? R : never
  • extends 분기문에서만 사용 가능하다
  • T가 { length: infer R }의 부분집합이고 R을 추론할 수 있으면 R로 분기
  • 그렇지 않다면 never로 분기

[출처] https://velog.io/@gomjellie/You-dont-know-type#%EF%B8%8F-%ED%83%80%EC%9E%85%EC%9D%80-%ED%8A%9C%EB%A7%81-%EC%99%84%EC%A0%84%ED%95%98%EB%8B%A4