관리 메뉴

꿈꾸는 개발자

3장 유니언과 리터럴 본문

Learning Typescript

3장 유니언과 리터럴

rickysin 2023. 2. 25. 22:51

타입스크립트에서 행해지는 ‘코드 정보에 입각한 추론’

  • 유니언(Union): 값에 허용된 타입을 두 개 이상의 가능한 타입으로 확장하는 것
  • 내로잉(narrowing): 값에 허용된 타입이 하나 이상의 가능한 타입이 되지 않도록 좁히는 것

3.1 유니언 타입


let thinker = Math.random()>5 //let thinker: string | undefined으로 표시됨
?undefined: "Mark Goldberg";
  • 위 코드처럼, undefined이거나 string일 수 있는 것과 같은 타입을 유니언이라고 한다.

3.1.1 유니언 타입 선언


  • 변수 초기값이 있더라도, 명시적 타입 애너테이션을 제공하는 경우 유니언 타입 사용 ⇒ 유니언 타입은 타입 애너테이션으로 타입을 정의하는 모든 곳에 사용 가능!
let thinker : string | null=null; 

if(Math.random()>0.5){
    thinker= "Susanne Langer";
}
  • 명시적으로 stirng | null 타입 애너테이션은 thinker의 값으로 string 타입의 값을 할당할 수 있음을 의미!(순서 중요X)

3.1.2 유니언 속성


  • 유니언 타입외에 접근할 경우 검사 오류가 발생!
let physicist = Math.random()>0.5 ? "Marie Curie":84;

physicist.toString(); //가능함! 

physicist.toUpperCase(); //string | number 에 사용 불가! number type에 해당하는 함수가 아니기 때문에!

physicist.toFixed(); // 동일하게 string에 사용할 수 없어서 안됨(둘을 동시에 고려함!)
  • 유니언 타입 중 특정 타입으로 된 값의 속성을 사용하려면 ⇒ narrowing이 필요함!

3.2 내로잉


  • 값 정의/선언/이전 유추 ⇒ 더 구체적인 타입임을 코드에서 유추하는 것 ⇒ 사용되는 논리적 검사(타입 가드(type guard))
  • 흔히 사용되는 두 가지 타입 가드

3.2.1 값 할당을 통한 내로잉


  • 변수 직접 할당?
let admiral:number | string;
admiral= "Hello";

admiral.toUpperCase(); //사용 가능 특정 타입으로 narrowing됐기 때문에! 

admiral.toFixed() //당연히 안됨
let inventor:number | string="hello"; // default값으로 할당했기 때문에 string으로 자동 narrowing
inventor= "Hello";

inventor.toUpperCase(); 

inventor.toFixed()

3.2.2 조건 검사를 통한 내로잉


  • if문으로 타입 확인하기
let scientist = Math.random()>0.5 ? "Rosa" : 51;

if(scientist === "Rosa"){
    scientist.toUpperCase();
}

scientist.toUpperCase(); //이건 안됨 에러 발생

3.2.3 typeof 검사를 통한 내로잉


let research= Math.random()>0.5 ? "Rosa": 51; 

if(typeof research === "string"){
    research.toUpperCase();
}

//부정 연산자 사용!
if(!(typeof research === "string")){
    research.toFixed();
}else{
    research.toUpperCase();
}

//삼항연산자 사용! 
typeof research === "string" ? research.toLowerCase(): research.toFixed();

  • typeof는 자주 사용하는 실용적인 방법

3.3 리터럴 타입


  • 조금 더 구체적인 버전의 원시 타입
const philo = "Hoin";

//물론 string 타입이다 => 하지만, 특정 값이 들어 있으니 타입은 기술적으로 "Hoin"이다 
//이게 바로 리터럴 타입 개념
  • 원시값의 특정 타입이 아닌, 특정 원시값으로 알려진 타입이 리터럴 타입!
    • string 타입은 표현 가능한 모든 문자열 집합을 의미
    • 리터럴 타입인 “Hoin”은 하나의 문자열만 나타냄
    • VS code에서 const로 선언된 변수 위에 마우스를 올려놓으면 타입 대신에 해당 값을 보여줌
    • boolean, null, undefined 외에도 number,string에 무수한 리터럴 타입이 존재
      • boolean: true | false;
      • null/undefined: 오직 자기 자신만을 가짐(하나의 리터럴)
      • number: 0 | 1 | ……………
let lifespan: number | "ongoing" | "uncertain";

lifespan=89; 
lifespan="ongoing";

lifespan=true; //error

3.3.1 리터럴 할당 가능성


  • 서로 다른 리터럴 값은 서로 할당 불가
let specific : "Ada";

specific="Ada"; //문제 없음

specific=" Bryo"; //error 발생 리터럴 타입이 맞지 않음!

let someStr=""; //string 타입

specific=someStr; //string은 type Ada에 할당될 수 없음

3.4 엄격한 null 검사


3.4.1 십억 달러의 실수


  • 다른 타입이 필요한 위치에서 null 값을 사용하도록 허용하는 많은 타입 시스템을 가리키는 업계 용어
  • 타입스크립트 컴파일러 실행 방식을 변경할 수 있는 다양한 옵션 중 (strictNullChecks)
    • 엄격한 null 검사 활성 여부를 결정 ⇒ 비활성하면 모든 코드의 모든 타입 | null | undfined를 추가해야 모든 변수가 null 또는 undefined을 할당 가능!
let nameMaybe= Math.random()>0.5
? "Hello": undefined;

nameMaybe.toLocaleLowerCase();
//strictNullChecks를 false로 설정하면 위 코드는 안전하다고 간주됨(실제로는 아님, undefined일
//경우 에러 발생)

//null 검사가 활성화되면 잠재적인 충돌을 확인한다. 
  • 핵심: 엄격한 null 검사를 활성화해라!

3.42 참 검사를 통한 내로잉


타입스크립트는 잠재적인 값 중 truthy로 확인된 일부만 변수의 타입을 좁힐 수 있다.

let nameMaybe= Math.random()>0.5
? "Hello": undefined;

//undefined일 경우 무조건 falsy하기 때문에 밑과 같이 작성 가능
if(nameMaybe){
    nameMaybe.toUpperCase();
}

nameMaybe.toUpperCase(); //에러 발생

3.4.3 초깃값이 없는 변수


let mathmatician:string; // 만약 string | undefined이면 에러 발생X

mathmatician?.length; //에러 발생 값이 할당되기 전에 사용했기 때문에! 

mathmatician= "hoin";
mathmatician.length; // 문제 없음!
  • undefined으로 선언하지 않고, 초깃값 없이 사용하려고 할 때 위와 같이 작동한다.

3.5 타입 별칭


let a:boolean| number| string |null |undefined; //5개 중 하나의 값을 가진다.
  • 재사용하는 타입에 더 쉬운 이름을 할당하는 타입 별칭 (type alias)이 존재함.
  • type 새로운 이름 = 타입 (형태를 가진다) → 파스칼 케이스로 이름을 지정함!
type MyName = "asdf"; //파스칼 케이스로 변수명 지정
  • 타입 별칭을 사용해 위처럼 긴 유니언 타입을 밑과 같이 축약할 수 있음
type Rawdata= boolean| number| string |null |undefined;

let a:Rawdata; 
let b: Rawdata;
let c: Rawdata;

3.5.1 타입 별칭은 자바스크립트가 아닙니다


  • 타입 별칭은 자바스크립트로 컴파일되지 않는다 (타입스크립트 시스템에만 존재)
  • 런타임 코드에서는 참조 불가! ⇒ 런타임에 존재하지 않기 때문에 접근하면 타입 오류!

3.5.2 타입 별칭 결합


  • 타입 별칭은 다른 타입 별칭 참조 가능!
type Id = number | string; 

// number | string | undefined | null 과 동일함
type IdMaybe= Id | undefined | null

=====================================================

//위 아래 순서는 상관없음!
type IdMaybe= Id | undefined | null
type Id = number | string; 

Reference:

조시 골드버그, 러닝 타입스크립트, 고승원 옮김, 2023