Type(2)

honeyricecake·2022년 8월 9일
0

타입스크립트

목록 보기
4/6

(1) Symbol

  • new Symbol 로 사용할 수 없다.
  • Symbol 을 함수로 사용해서 symbol 타입으로 만들어낼 수 있다.

ex.
console.log(Symbol('foo') === Symbol('foo'))
이는 false가 출력된다.
즉, 두개의 symbol은 완전히 독립적이다.

symbol은 프리미티브 타입의 값을 담아서 사용하는데, 교유하고 수정불가능한 값으로 만들어 준다.

그래서 주로 접근을 제어하는데 쓰는 경우가 많았다.

ex.

const sym = Symbol();

const obj = {
  sym: "value",
}

obj["sym"]

원래는 obj["sym"]으로 쉽게 접근이 가능하다.
그런데 이를

const sym = Symbol();

const obj = {
  [sym]: "value",
}

obj[sym]

이렇게 key값으로 sym변수 값을 이용하면 객체를 참조할 때도 반드시 sym변수를 사용해야 한다.

symbol은 이런 식으로 사용 가능하다.

함수로 사용할 때는 대문자 Symbol, 타입으로 사용할 때는 소문자 symbol 임을 잊지 말자.

(2) null & undefined

둘 다 소문자로만 존재하고 undefined 와 null은 실재로 각각 undefined와 null 이라는 타입을 가진다.

undefined와 null은 다른 모든 타입의 subtype으로 존재한다.
즉, number에 null또는 undefined를 할당할 수 있다는 의미이다.
하지만 컴파일 옵션(tsconfig의 옵션)에서 -strictNullChecks를사용하면, null과 undefined는 void나 자기 자신들에게만 할당할 수 있다.
(void에 undefined는 할당이 가능하나, null은 할당이 불가능하다.)

이 경우 null과 undefined룰 할덩할 수 있게 하려면, union type을 이용해야 한다.

ex.

// let myName: string = null;

let v :void = undefined

let union: string | null = null;

void 타입의 v에 값을 할당하여 초기화를 하려는데 void는 값으로 존재하지 않으므로 undefiined를 할당하는 것이 일반적이다.

그리고 위와 같이 union변수는 string 또는 null타입인데 이렇게 두 타입을 모두 쓸 수 있는 것을 union타입이라 한다.

자바스크립트에서의 null:

null 이라는 값으로 할당된 것을 null이라 한다.
무언가가 있는데, 사용할 준비가 덜 된 상태이다.
null이라는 타입은 null이라는 값만 가질 수 있는데,
런타임에서 typeof연산자를 이용해서 알아내면 object이다.

이는 자바스크립트의 typeof 연산자의 설계상 오류로 타입스크립트에서는 타입이 null로 지정되어 있다.

자바스크립트에서의 undefined:

값을 할당하지 않은 변수는 undefined라는 값을 가진다.
무언가가 아예 준비가 안된 상태이다.
object의 property가 없을 때도 그 property에 접근하면 undefined이다.
런타임에서 typeof 연산자를 이용해서 알아내면 undefined이다.

ex.

"use strict";
// let myName: string = null;
let v = undefined;
let union = null;
let n = null;
let x = {};
console.log(typeof n);
console.log(typeof x.hello);

타입스크립트에서는 객체에 존재하지 않는 속성을 참조하면 컴파일시 에러가 뜬다!

(3) object

object(객체)는 프리머티브 타입이 아니다.

const person1 = {name: 'honey', age: 30}
const person2 = Object.create({name: 'ricecake', age: 20})

이 두가지 방법으로 만들 수 있다.

object는 premitive 타입이 아닌 것을 나타내고 싶을 떄 사용하는 타입이다.
따라서 Array 등도 object 변수에 할당할 수 있다.
(레퍼런스는 모두 들어갈 수 있구나!)

(4) Array

Array(배열)는 같은 타입의 요소들을 모아놓은 것이다.
중요한 것은 하나의 타입이라는 것이다.

let list1: number[] = [1, 2, 3];
let list2: Array<number> = [1,2,3];

위 두가지 방법 모두 사용이 가능하나 충돌의 여지가 있기에 위의 방법을 대부분 선호한다.

let list: (number | string)[] = [1, 2, 3, '4'];

이렇게도 사용이 가능하다.

(5) Tuple

ex.

let x: [string, number];

x = ['hello', 39];

const person: [string, number] = ['Kim', 40]

const [first, second] = person;

x[2] 참조 불가, const [first, second, third] = person 불가.

(6) any

function returnAny(message: any) : any {
  console.log(message);
}  // 리턴 타입은 any
// 아무값이나 넣을 수 있을 때도 읽는 사람들을 위해 any를 명시해주어야 한다.

const any1 = returnAny("리턴은 아무거나");
// any는 최대한 사용하지 않는 것이 좋다.

any는 어떤 타입이어도 상관없는 타입이며, 이걸 최대한 쓰지 않는 것이 핵심이다.
왜냐면 컴파일 타임에 타입 체크가 정상적으로 이뤄지지 않기 때문이다. (타입스크립트를 쓰는 의미 X)
그래서 컴파일 옵션 중에는 any를 써야 하는데 쓰지 않으면 오류를 뱉도록 하는 옵션이 있다. (nolmplicitAny)

let looselyTyped: any = {};
const d = looselyTyped.a.b.c.d;

이 때 d의 타입은 any이다. 이를 any의 전파라고 한다.
즉, any가 들어간 경우, 코드가 안정성을 잃을 수 있다.
이를 방지하기 위해서는 코드를 다음과 같이 짜야한다.

function leakingAny(obj: any) {
  const a: number = obj.num;
  const b = a + 1;
  return b;
}

중간에 타입을 지정해줘서 누수를 막는 것이다.

사실 이렇게 any를 어떤 타입으로 지정해줄 수도 있지만 더 좋은 것은 obj를 사용하기 전에 TypeGuard(typeof, instance 등등) 같은 형식으로 갈라내서 타입이 지정되도록 unknown 같은 방식을 사용하는 것을 추천한다.

(7) unknown

any가 주는 불안성을 조금이나마 해소하기 위한 대체제라고 할 수 있다.

응용프로그램을 작성할 때 모르는 변수의 타입을 묘사해야 할 수도 있다.
이러한 값은 동적 콘텐츠(예: 사용자로부터, 또는 우리 API의 모든 값을 의도적으로 수락하기를 원할 수 있다.)

이 경우, 컴파일러와 미래의 코드를 읽는 사람에게 이 변수가 무엇이든 될 수 있음을 알려주는 타입을 제공하기를 우너하므로 unknown 타입을 제공한다.

ex.

declare const maybe: unknown;

const aNumber : number = maybe;  // 에러

unknown 은 number에 바로 assign할 수 없다.

Tip.

let x = 1
console.log(x === true)
console.log(x == true)

if(x)
{
    console.log("wow")
}

else
{
    console.log("ㅠㅠ")
}

위의 코드는 각각 false, true, wow 가 출력된다.

ex.

let maybe: unknown;

maybe = true;

if(maybe === true) {
  const aBoolean: boolean = maybe;

  const aString: string = maybe;  // 에러
}

이 때 maybe === true이면 maybe는 boolean 이므로 if문 안에서 maybe 는 boolean으로 인식된다.

그래서 변수 aBoolean에는 그 값이 할당되나 그 밑줄에서는 에러가 난다.

if(typeof maybe === 'string')
if문안에서 maybe는 string으로 인식된다.
이런 것을 타입가드라고 부른다.

타입가드를 통해 타입을 한정시켜야만 쓸 수 있는 것을 unknown이라 한다.

any와 같이 아무거나 할당할 수 있으나 컴파일러가 타입을 추론할 수 있게끔 타입의 유형을 좁히거나 타입을 확정해주지 않으면 다른 곳에 할당할 수 없고 사용할 수 없다.
unknown 타입을 사용하면 런타임에러를 줄일 수 있다.
사용전에 데이터의 일부 유형의 검사를 수행해야하는 API에 사용할 수 있다.

(8) never

보통 return문에 사용된다.

ex1.

function error(message: string): never {
  throw new Error(message);
}

ex2.

function fail() {
  return error("failed");
}

ex3.

function infiniteLoop(): never {
  while(true) {}
}

never 타입은 모든 타입의 subtype이며 모든 타입에 할당할 수 있다.
하지만 never에는 그 어떤 것도 할당할 수 없다.
잘못된 타입을 넣는 실수를 막고자 할 때 사용되기도 한다.

declare const a: string | number ;

if(typeof a !== 'string') {
  a;
}

이 경우 if문안의 a는 number 타입이다.

declare const a: string;

if(typeof a !== 'string') {
  a;
}

이 경우는 never 타입이다.
즉, a가 string으로 선언되었는데도 a가 string이 아닌 경우를 지정해 변수를 할당하는 경우를 막기 위해 a는 never타입이 되어 변수가 할당되지 않게 된다.

(9) void

어떤 타입도 가지지 않는 빈 상태를 의미한다.
자바스크립트에는 undefined가 있어서 필요가 없었으나 다른 언어들에 있어서 의미상 통일을 위해 사용하게 되었다.

ex.

function returnVoid(message: string): void
{
  console.log(message);
  return;
}

이렇게 아무것도 리턴하지 않을 때 void라고 명시해줄 수 있다.
명시하지 않을 수도 있다.

0개의 댓글