Elice

[TIL]엘리스트랙 5주차 3일 TypeScript

NHyun 2023. 9. 6. 12:06

타입스크립트란?

  • Microsoft에서 개발하고 유지/관리가 되는 Apache 라이센스가 부여된 오픈 소스
  • 자바스크립트의 상위 확장자 즉 슈퍼셋이며, 자바스크립트에 '타입'을 부여한 언어
  • 자바스크립트의 한계를 해결

 

 

타입스크립트를 사용하는 이유

  • 자바스크립트의 동적 타입을 정적 타입으로 선언이 가능하다.
  • 타입 유추를 통해 타입 제어가 가능하다.
  • 자바스크립트에서 찾을 수 없는 추가 코드 기능을 제공한다.
  • 자바스크립트의 런타임 단계에서 발생하는 타입 에러는 타입스크립트를 이용한다면 컴파일 단계에서 미리 확인하고 고칠 수 있다.

TypeScript의 Type

기본자료형 (primitive type)

-Object와 reference 형태가 아닌 실제 값을 저장하는 자료형, primitive type 내장함수를 사용 가능한 것은 자바스크립트의 처리 방식 덕분

 

종류

 

-string(문자열 값)

let str:string = 'hi';

-boolean(진위 값)

let isSucceeded:boolean = 'true';

-number(부동 소수 값 / 2진수, 8진수, 10진수, 16진수 사용가능)

// let num:number = '10';     let hex:number = '0xf00d;      let binary:number = 0b1010;
// NaN은 number 타입에 해당한다.
let notANumber: number = NaN;
// 천단위로 _를 사용해 끊어 표기해도 가능하다.
let underScore: number = 1_000_000;

-null(값이 의도적으로 비어있는 상태)

let n:null = null;

-undefined(아무 값도 할당되지 않은 상태)

let u:undefined = undefined;

-symbol(ES6 추가)

// 타입스크립트에서 Symbol타입이 인식이 안될 땐 tsconfig.json파일에서 "lib" : [], 주석을 해제하고 ["ES2015", "DOM"]을 추가한다.
console.log(Symbol("foo")); // Symbol은 String이나 Number와 같은 래퍼 객체가 아니다.
console.log(Symbol("foo") === Symbol("foo")); //false

Symbol은 프라이미티브 타입의 값을 담아서 사용한다.
Symbol은 해당 값을 고유하고 수정 불가능한 값으로 만들어준다.
따라서 주로 접근을 제어하는데 많이 쓰인다

 

참조자료형(reference type)

-객체, 함수, 배열 등과 같은 object형식의 타입,메모리에 값을 주소로 저장하고, 출력 시 메모리 주소와 일치하는 값을 출력

 

종류

 

-object(기본 자료형에 해당하지 않는 타입)

const person1 = { name: "Mark", age: 39 };
// person1은 타입스크립트 관전에서 object 타입이 아니다.
console.log(typeof person1); // "{name: string, age: number}" type.

const person2 = Object.create({ name: "Mark", age: 39 }); // 괄호 안에는 객체 형태 또는 null을 넣을 수 있다.
const person3 = Object.create(39); // error
const person4 = Object.create([]); // 배열도 가능하다.
const person5 = Object.create(function () {}); // 함수도 가능하다.

// 함수는 주로 아래와 같이 사용한다.
declare function create(o: object | null): void;
create({ prop: 0 }); //ok
create(null); //ok
create(42); // error
create("string"); // error
create(false); // error
create(undefined); // error

-Array(배열 타입)

// 배열 타입을 표현하는 두가지 방법
let arr: number[] = [1, 2, 3];
//아래와 같이 제네릭을 사용가능
let arr: Array<number> = [1, 2, 3]; // 리액트와 사용할 때 jsx언어와 충돌할 수 있어서 첫번쨰 표현식을 권장한다.

let arr: (number | string)[] = [1, 2, 3, "4"]; // union type으로도 지정 가능하다.

추가 제공 자료형

-TypeScript에서 개발자의 편의를 위해 추가로 제공하는 타입

 

종류

-tuple(길이와 각 요소의 타입이 정해진 배열을 저장하는 타입)

let arr : [string,number] = ['Hi', 6];
arr[1].concat('!'); //Error =, 'number' does not have 'concat'
arr[3] = 'hello' //정의하지 않은 index 호출 시 오류

-enum(특정 값(상수)들의 집합을 저장하는 타입) //자바스크립트로 컴파일하면 enum값이 사라짐

enum Car{ BUS, TAXI, SUV };

let bus: Car = Car.BUS;
let bus: Car = Car[0]; //인덱스 번호로 접근가능

//인덱스 사용자 편의로 변경
enum Car { BUS=1, TAXI=2, SUV=3 };
let taxi: String = Car[2];

eumCar { BUS=2, TAXI, SUV};
let taxi: String = Car[3];

-any(모든 타입을 저장 가능, 컴파일 중 타입 검사를 하지 않음 / 시스템의 안정성을 위해 사용을 권장하지 않음)

function returnAny(message: any): any {
  // 이 함수의 리턴값은 어떤 값도 될 수 있다.
  console.log(message);
}

// any 타입은 전파된다.
function leakingAny(obj: any) {
  const a = obj.num;
  const b = a + 1;
  return b;
}
// function 안 변수들의 타입은 모두 any이다.
const c = leakingAny({ num: 0 });

function leakingAny(obj: any) {
  const a: number = obj.num; // 이렇게 누수를 막으면 이 이후에 변수들의 타입은 number가 된다.
  const b = a + 1;
  return b;

-void(보통 함수에서 반환 값이 없을 때, any의 반대 타입, 변수에는 undefined와 null만 할당하고, 함수에는 반환 값을 설정할 수 없는 타입)

function returnVoid(message: string) {
  // return이 없는 함수의 경우 기본 타입은 void
  console.log(message);
}

const r = returnVoid("리턴이 없다."); // 여기서 r의 타입도 void가 된다.
const r: undefined = returnVoid("리턴이 없다."); // Error!

function returnVoid(message: string): void {
  // void가 지정된 함수는 해당 함수의 리턴값을 사용하지 않겠다는 명시적 표현이다.
  console.log(message);
  return undefined; // 유일하게 undefined만 리턴할 수 있다.
}

-never(발생할 수 없는 타입, 항상 오류를 발생시키거나 절대 반환하지 않는 반환 타입, 종료되지 않는 함수)

function error(message: string): never {
  throw new Error(message);
  //return 값이 없기 때문에 never를 지정할 수 있다.
}

function fail() {
  // 리턴하고 있는 에러 함수에 리턴 타입이 never이기 때문에 이 함수의 return 타입도 never이다
  return error("failed");
}

function infiniteLoop(): never {
  while (true) {}
  // 출구 없는 while 문으로 return 값이 없어 return type은 never 이다.
}

function neverEnd():never {
 while(true) {
 break;              /break로 함수가 종료되기에 에러 출력
   }
}             

let a: string = "hello";
if (typeof a !== "string") {
  a; // 여기서 a의 타입은 never이다.
}

declare const b: string | number;
if (typeof b !== "string") {
  b; // 여기서 b의 타입은 number이다.
}

Utility types

-유틸리티 타입은 이미 정의해 놓은 타입을 변환할 때 사용하기 좋은 타입 문법입니다. 유틸리티 타입을 꼭 쓰지 않더라도 기존의 인터페이스, 제네릭 등의 기본 문법으로 충분히 타입을 변환할 수 있지만 유틸리티 타입을 쓰면 훨씬 더 간결한 문법으로 타입을 정의할 수 있습니다.

 

참조: https://www.typescriptlang.org/docs/handbook/utility-types.html#handbook-content

 


TypeScript를 이용해 함수 작성하기

  • TypeScript 함수 작성 시 반환 타입을 추론 하도록 하는 걸 권장한다.
  • 함수의 매개 변수와 인수의 타입이 호환 가능하게 작성한다.
  • 인수의 타입을 잘못 전달하면 에러가 발생한다.

 

타입 추론

  • TypeScript 컴파일러는 방정식의 한쪽에만 타입이 있더라도 타입을 추론할 수 있다.
  • 이러한 타입 추론 형태를 "contextual typing"이라고 한다.
  • 이를 통해 프로그램에서 타입을 유지하기 위한 노력을 줄일 수 있다.
//일반적인 함수
let f12 = function(x: number, y: number): number {
 return x+y;
}

//contextual typing
let f12: (basevalue: number, increment: number) => number = function(x,y) {
 return x+y;
}

 

기본 매개변수(Parameter)

  • 함수에 주어진 인자의 수는 함수가 기대하는 매개변수의 수와 일치해야 한다.
function buildName(fristName : string, lastName : string) {
 return firstName + " " + lastName;
}

let result1 = buildName("Bob") // Error:Expected 2 arguments, but got 1
let result2 = buildName("Bob", "Admas", "Sr."); //Error: Expcted 2 2arguments, but got 3
let result3 = buildName("Bob", "Admas");

선택적 매개변수(Optional Parameter)   // 무조건 맨 뒤에만 사용가능

  • JavaScript에서는 모든 매개변수가 선택적으로, 인수가 없다면 undefined가 된다.
  • TypeScript에서도 선택적 매개변수를 사용할 수 있다. (사용시 변수명 뒤에 ? 사용)

 

function buildName(fristName:string lastName?:string) {
 if(lastName)return firstName + " " + lastName;
 else return fristName;
}

let result1 = ("Bob");
let result2 = ("Bob", "Adams");
let result3 = ("Bob", "Admas", "Sr.");     // Error: expected 2 arguments, but got 3

기본-초기화 매개변수(Default Parameter)

  • TypeScript에서는 값을 제공하지 않거나, undefined로 헸을 때에 매개변수의 값 할당 가능
function buildName(firstName:string, lastName="Smith") {
 return fristName + " " + lastName;
}

let result1 = buildName("Bob"); // "Bob Smith"
let result2 = buildName("Bob", undefined); // "Bob Smith"
let result3 = buildName("Bob", "Admas"); // "Bob Admas"
let result4 = buildNames("Bob", "Admas", "Sr."); //Error:Expected 1-2arguments, but got 3.

 

나머지 매개변수(Rest Parameter)

  • 컴파일러 생략 부호(...)뒤의 인자 배열을 빌드해 함수에서 사용할 수 있다.
  • 나머지 매개변수는 매개변수의 수를 무한으로 취급한다.
  • 아무것도 넘겨주지 않을 수 있다.
function buildName1(firstName:string, ...restOfName:string[]) {
//restOfName= ["Samuel", "Lucas", "James"]
return firstName+" "+restOfName.join("");
}

let employeeName = buildName("Joseph", "Samuel", "Lucas", "James");