TypeScript -Basic type-3

0

<TypeScript -Basic type-3>

type Alias와 String Literal Type, union Types, Disciminated Unions, Enum , type interferece에 대해 알아보자!

Type Alias

  • alias의미에서 알 수 있듯이 기본 타입외에 사용자가 원하는 타입을 생성 하여 사용 할 수 있는 타입이다.
  • 원시형(primitive) 타입외에 객체(object)의 타입도 지정 해줄 수 있다.
// Text란 타입은 없지만 사용자가 text 타입아래와 같이 정의하면 text란 타입은 문자열의 타입이 된다.
type Text = string;
const address: Text = "no War"
const test: Text = 'hello world!'
type Num = number; // Num이라고 문자열 타입도 정의가능하다.

//object property type 
type Student = {
  name: string;
  age: number;
};

const student: Student = {
  name: 'Nowar',
  age: 2022,
};

const student: Student = {
  animal: 'dog' // name 프로퍼티가 없기 때문에 error 발생, name의 문자열과 ,age숫자 타입가 있어야 에러발생하지 않음!
}

String Literal Type

  • 특정 값 자체를 타입으로 할당하여 지정 할 수도 있다.
type Name = 'name';
let clubName: name;
myName = 'name';
myName = 'chelsi'; // 'name'이 아니기 때문에 error 발생한다.

type JSON = 'json';
const json: JSON = 'json';

type Bool = true;
const isCat: Bool = true;
const isCat: Bool = false; // true 가 아니기 때문에 error 발생

Union Types

  • 프로그래밍 언어에서 or 과 비슷한 역할을 한다.
  • 발생하는 다양한 케이스 중에서 하나만 정하고 싶을 때 사용한다
type Direction = 'left' | 'right' | 'up' | 'down';

function move(direction: Direction) {
  console.log(direction);
}

move('right');
move('left');
move('hello world') // error : 위에서 설정한 4가지의 경우의 값을 제외한 경우 에러가 발생!
  • String literal type과 조합하면 활용도가 높다.

로그인의 상태를 리턴해주는 함수를 만든다고 가정해봅시다.

// login 의 함수로서 로그인이 성공하면 sucees, 실패하면 fail과 이유가 잇는 함수라고 해보자

type SuccessState = {
  response: {
    body: string;
  }
}

type FailState = {
  reason: string;
}

// 이렇게 만들어 줄 수 있겠지만 로그인의 타입을 아래와 같이 만들어줌으로서 type을 지정해서 관리 해줄 수 있다. 
//before
function login():SuccessState | FailState {}
type LoginState = SuccessState | FailState;


// after: union type 적용 후
function login(id: string, password: string): LoginState {
// Promise<LoginState> 실제 프로젝트에서는 프로미스겠죠?
  return {
    response: {
      body: 'logged in!',
    },
  };
}

Discriminated Unions

  • union 타입에서 차별화되는 이름이 동일한 타입을 가지고 있으면서 간편하게 구분히 가능한 타입이라고 할 수 있다.
    • 즉, 공통적인 property를 가지고 있음으로서 좀더 구분하기 쉽게 만들다라고 이해하면 될 것 같다
//로그인이 성공했디고 가정하고 성공했을시 req.body를 출력해주고, 실패 했을 시 실패에 대한 이유가 나온다고 해보자!
// 리턴이 없기 때문에, void타입은 생략되어 있음!

function printLoginState(state: LoginState) {
//보편적으로는 아래처럼 사용해서 response있다면 성공의 경우 출력을 해주고 실패한 경우, 아래처럼 로직을 짤 수 있다.
  if ('response' in state) {
    console.log(`🚀 ${state.response.body}`);
  } else {
  // console.log(${state.response.body}) 이런 식으로 접근 하게 된다면, 
  //이 경우의 성공, 실패 두가지 경우 이므로 에러를 잡아주기는 한다. 
    console.log(`😇 ${state.reason}`);
  }
}

//동일한 key 인 result를 각 성공 실패 상태마다 갖고 있지만, 어떤 state냐에 따라 다른 타입이 지정되도록 하여,  타입이 보장되면서 서로 다른 state를 만들 수 있다.
type SuccessState = {
  result: 'success';
  response: {
    body: string;
  };
};
	
type FailState = {
  result: 'fail';
  reason: string;
};

type LoginState = SuccessState | FailState;

function printLoginState(state: LoginState) {
  state.result; // success or fail
  if (state.result === 'success') {
    console.log(`🚀 ${state.response.body}`);
  } else {
    console.log(`😇 ${state.reason}`);
  }
 }
}

Intersection Type

  • 프로그래밍 언어에서 & 과 비슷한 역할을 한다.
  • 다양한 타입들을 묶어서 사용 할 수 있다.
	// 아래과 같이 student 타입과 worker를 지정해줬다고 하자.
	type Student = {
    name: String;
    score: number;
  };

  type Worker = {
    empplyeeId: number;
    work: () => void;
  };

	// 인턴쉽을 하는 근로자는 학생이면서 일하는 사람일 수 있다.
  function internWork(person: Student & Worker) {
    console.log(person.name, person.empplyeeId, person.work());
  }

  internWork({
    name: "iam intern",
    score: 8,
    empplyeeId: 2342,
    work: () => {},
  });

Enum type

  • 하나의 집합과 관련된 상수들을 한 곳에 모아서 관리할 수 있는 타입이라고 할 수 있다.

JavaScript 에서의 집합 예시

  • 대문자를 사용해서 상수라는 것을 나타낸다.
  • Object.freeze({}) 를 사용해서 외부에서 변경할 수 없는 객체를 지정할 수 있다.
//javscript : Object.freeze()를 사용해서 집합을 묶어 불변한 객체를 관리 할 수 있다.

const MONDAY = 0;
const TUESDAY = 1;
const WEDNESDAY = 2;
const DAYS_ENUM = Object.freeze({ MONDAY: 0, TUESDAY: 1, WEDNESDAY: 2 });
const dayOfToday = DAYS_ENUM.MONDAY;

TypeScript의 enum

  • 앞에만 대문자 그 뒤는 소문자로 작성한다.
  • 값을 따로 주지 않을 시 , 자동적으로 value 값은 0,1,2,3,4.. 순으로 지정 됨.
// 값을 할당시!
	//enum Days {
  //  Monday = "Monday",
  //  Tuesday = "tuesday",
  //  Wednesday = "wed",
  //  Thursday = "thur",
  //  Friday = "fri",
  //  Saturday = "sat",
  //  Sunday = "sun",
  //}

//할당을 따로 안 할 시,
enum Days {
  Monday,    // 0
  Tuesday,   // 1
  Wednesday, // 2
  Thursday,  // 3
  Friday,    // ...
  Saturday,  
  Sunday,    
}

console.log(Days.Monday); // 0이 할당됨
let day = Days.Friday // 4
 // 현재 day 변수는 Days(enum)타입을 가질 수 있는데 이 때,
 // enum이 가지고 있는 타입을 임의로 지정할 수 있다.

day = Days.Friday;
day = 10; // 컴파일 에러가 발생하지 않음!
console.log(day);

대체방안으로 union Type을 대신하여 활용이 가능하다.

type Day = 'Monday' | 'Tuesday' | 'Wednesday' | 'Thursday' | 'Friday' | 'Saturday' | 'Sunday'
let dayOfWeek: Day = 'Monday'
  • enum의 사용 예시
type Errors = 'error message simple version' | 'error message complicated version' | 'error message complicated detail version';

// 이렇게 복잡한 union의 경우에는 아래처럼 enum으로 해줄 수 도 있지 않을까 생각한다. (엘리님 의견)
  enum Errors {
    Short: 'error message simple version' ,
    Long: 'error message complicated version',
    Detail: 'error message complicated detail version'
  }

Type inference(타입 추론)

  • 영어 문맥 의미에서 알 수 있듯이 , 최초에 변수를 선언하고 할당 할 때의 타입을 추론해서 지정하는 것을 말한다.
  • 함수의 void 타입이라면 생략이 가능하나, 타입 추론을 사용하기는 지양하는 편이 좋다.
let text = 'hello'; // 이경우 문자열이 할당하면 타입을 따로 명시하지 않으면, 타입은 문자열이라고 ts에서 타입을 추론함
text = "hello world";
text = 1; // error 발생 문자열로 추론했기 때문에.

// 함수의 매개변수에는 자동으로 any로 추론한다. 그러므로 type을 지정해주는 것이 좋다.
function print(message) {
  console.log(message)
}

print('hello')
print(1)
  • default parameter를 지정해줄 경우 지정된 parameter 의 타입으로 지속적으로 추론한다.
function printStr(message = 'hi') {
  console.log(message)
}

printStr('hello');
printStr(1); // error
  • 들어오게될 매개변수의 타입이 둘 다 number 타입이므로 return 값의 타입도 number 일 것이라고 추론한다.
function add(x: number, y: number) {
  return x + y;
}

// add 함수는 return 값을 number 타입으로 추론했따.
// 그 함수의 리턴 값을 변수에 담는다면, 그 변수 또한 number 타입이라고 추론한다.
//
const result = add(1, 2);

//하지만, 아래처럼 더욱 구체적으로 명시를 해주는 것이 좋을 것이다. 
function add(x: number, y: number):number {
  return x + y;
}

Type Assertion (타입 표명)


  • 자바스립트 라이브러리와 같은 타입이 없는 자바스크립트와 연동이 되기 때문에 불가피하게 사용하게 될 경우를 위해 제공되어진다.

  • type을 장담하는 경우 사용 할 수 있으나 그래도 지양하는 것이 좋다.

  // 아래와 같은 js함수가 있다고 하면 , 리턴은 문자열을 리턴하는 함수라고 있다고 하자
  function jsStrFunc(): any {
    return "hello";
  }

  // 내부적으로 문자열이 반환 되는 것을 알고 있고 아래의 result 변수에 담고 스트링의 메서드를 사용하고 싶다면 어떻게 해야할까?
  const result = jsStrFunc();

  //아래처럼 사용 가능하다!
  console.log((result as string).length);
  console.log((<string>result).length);  

하지만 실제 함수 반환값이 hello의 문자열이 아닌 숫자를 반환한다면? 에러가 발생하고 undefined를 반환 할 것이다.

// 아래의 함수는 number 배열을 반환한거나 혹은 undefined반환 하는 함수라고 해보자
	function findNumbers2(): number[] | undefined {
    return undefined;
  }
  const numbers = findNumbers2();
  numbers.push(2); // 😱 // 느낌표는 절대적으로 값이 있다고 확신하고 함! undefined될 수 없다고 장담하고 하는 것..

	const numbers = findNumbers2()!; // 이처럼 함수에 느낌표를 붙이거나 아래의 느낌표를 붙여 사용 가능
	numbers.push(3);

	const numbers = findNumbers2();
	numbers!.push(2) 

// 이런식으로 장담하다고 하다보면, 어플리케이션이 죽을 수도 있기 때문에 가능하면 사용을 피하는 것이 좋을거 같다.
profile
문과생 개발자되다

0개의 댓글