JavaScript/TypeScript

TS 타입 시스템

IT Blue 2021. 6. 17. 00:25

 

타입 시스템

 

- 컴파일러에게 사용하는 타입을 명시적으로 지정하는 시스템

- 컴파일러가 자동으로 타입을 추론하는 시스템

 

TS의 타입 시스템

 

- 타입을 명시적으로 지정할 수 있다

- 타입을 명시적으로 지정하지 않으면, 타입스크립트 컴파일러가 자동으로 타입을 추론

 

noImplicitAny 옵션

 

- 해당 옵션을 사용하면 타입을 명시적으로 지정하지 않은 경우, 타입스크립트가 추론 중 'any' 라고

판단하게 되면, 컴파일 에러를 발생시켜 명시적으로 지정하도록 유도한다

 

strictNullChecks 옵션

 

- 해당 옵션을 사용하면 모든 타입에 자동으로 포함되어 있는 'null' 과 'undefined' 를 제거

 

nolmplicitReturns 옵션

 

- 해당 옵션을 사용하면 함수 내에서 모든 코드가 값을 리턴하지 않으면, 컴파일 에러를 발생

 

strictFunctionTypes 옵션

 

- 해당 옵션을 사용하면 함수를 할당할 시에 매개변수 타입이 같거나 슈퍼타입인 경우가 아닌 경우,

에러를 통해 경고

 


 

Structural Type System

 

- 구조가 같으면, 같은 타입이다 (TS 타입 체계)

 

interface IPerson {
  name: string;
  age: number;
  speak(): string;
}

type PersonType = {
  name: string;
  age: number;
  speak(): string;
};

let personInterface: IPerson = {} as any;
let personType: PersonType = {} as any;

personInterface = personType;
personType = personInterface;

 

Nominal Type System

 

- 구조가 같아도 이름이 다르면, 다른 타입이다 (대표적인 언어는 C언어, Java 등)

 


 

타입 호환성 (Type Compatibilty)

 

  • 서브 타입

 

// sub1 타입은 sup1 타입의 서브 타입이다
let sub1: 1 = 1;
let sup1: number = sub1;
// sub1 = sup1; (에러)

// sub2 타입은 sup2 타입의 서브 타입이다
let sub2: number[] = [1];
let sup2: object = sub2;
// sub2 = sup2; (에러)

// sub3 타입은 sup3 타입의 서브 타입이다
let sub3: [number, number] = [1, 2];
let sup3: number[] = sub3;
// sub3 = sup3; (에러)

 

// sub4 타입은 sup4 타입의 서브 타입이다
let sub4: number = 1;
let sup4: any = sub4;
sub4 = sup4;

// sub5 타입은 sup5 타입의 서브 타입이다
let sub5: never = 0 as never;
let sup5: number = sub5;
// sub5 = sup5; (에러)

class Animal {}
class Dog extends Animal {
  eat() {}
}

// sub6 타입은 sup6 타입의 서브 타입이다
let sub6: Dog = new Dog();
let sup6: Animal = sub6;
// sub6 = sup6; (에러)

 

// 1. 같거나 서브 타입인 경우, 할당이 가능하다 => 공변

// primitive type
let sub7: string = '';
let sup7: string | number = sub7;

// object - 각각의 프로퍼티가 대응하는 프로퍼티와 같거나 서브타입이어야 한다
let sub8: { a: string, b: number} = { a: '', b: 1 };
let sup8: { a: string | number; b: number } = sub8;

// array - object 와 마찬가지
let sub9: Array<{ a: string; b: number}> = [{ a: '', b:1 }];
let sup9: Array<{ a: string | number; b: number}> = sub9;

 

// 2. 함수의 매개변수 타입만 같거나 슈퍼타입인 경우, 할당이 가능하다 => 반병

class Person {}
class Developer extends Person {
  coding() {}
}
class StartupDeveloper extends Developer {
  burning() {}
}

function telme(f: (d: Developer) => Developer) {}

// Developer => Developer 에다가 Developer => Developer 를 할당하는 경우
telme(function dToD(d: Developer): Developer {
  return new Developer();
});

// Developer => Developer 에다가 Person => Developer 를 할당하는 경우
telme(function pToD(d: Person): Developer {
  return new Developer();
});

// Developer => Developer 에다가 StartupDeveloper => Developer 를 할당하는 경우
// 에러 발생
// telme(function sToD(d: StartupDeveloper): Developer {
//   return new Developer();
// });

 


 

타입 별칭 (Type Alias)

 

- Interface 랑 비슷해보임

- Primitive, Union Tpye, Tuple, Function

- 기타 직접 작성해야하는 타입을 다른 이름을 지정할 수 있다

- 만들어진 타입의 refer(별명)로 사용하는 것이지 타입을 만드는 것은 아니다

 

// Aliasing Primitive

type MyStringType = string;

const str = 'world';

let myStr: MyStringType = 'hello';
myStr = str;

 

// Aliasing Union Type

let person: string | number = 0;
person = "Lee";

type StringOrNumber = string | number;

let another: StringOrNumber = 0;
another = 'Park';

// 유니온 타입은 A도 가능하고 B도 가능한 타입
// 길게 쓰는걸 짧게 사용

 

// Aliasing Tuple

let person: [string, number] = ['Lee', 25];

type PersonTuple = [string, number];

let another: PersonTuple = ['Park', 35];

// 튜플 타입에 별칭을 줘서 여러 곳에서 사용이 가능하다

 

// Aliasing Function

type EatType = (food: string) => void;