[엘리스 sw 엔지니어 트랙] 24일차 TypeScript

오경찬·2022년 5월 12일
0

수업 24일차

오늘은 타입스크립트 2일차이다. 어제 타입스크립트에 대해서 어떤것이고 왜쓰는지 그리고 맛보기 용으로 js의 파일을 ts로 바꾸는 실습 정도를 진행했다면 오늘은 타입스크립트에 대해 이런거 까지 있어요!! 하는 내용을 배우게 되었다.

이론

  • 타입스크립트 : 자바스크립트의 상위 집합,
    쓰는이유: 정적으로 선언가능, 타입 유추를 통한 타입 제어 가능, 오류포착 가능, js에서 찾을수 없는 추가 코드 제공
    기본 자료형: string(문자열 저장), boolean(참/거짓 저장), number(숫자 저장), null(의도적으로 비어있는), undefined(아무값이 할당x)
    참조 자료형: object(기본 자료형에 해당x), array(배열을 저장함)
    추가 제공 자료형: tuple(길이와 각요소의 타입이 정해진 배열), enum(특정 값들의 집합), any(모든 타입을 저장), void(보통 함수에서 반환값이 없을때 사용, any반대), never(발생할수 없는 타입, 종료되지 않는 함수)
    Partial< T>: 주어진 타입의 모든 하위 타입 집합을 나타내는 타입을 반환
    Readonly< T>: 프로퍼티를 읽기 전용으로 설정한 타입
    Record< T>: 타입의 프로퍼티들을 다른 타입에 매핑시키는데 사용
    Pick<T,K>: 프로퍼티 K의 집합을 선택해 타입을 구성
    Omit<T,K>: 모든 프로퍼티를 선택한 다음 K를 제거한 타입을 구성
    Exclude<T,U>: T에서 U에 할당할 수 있는 모든 속성을 제외한 타입을 구성
    Extract<T,U>: T에서 U에 할당 할 수 있는 모든 속성을 추출하여 타입을 구성
    NonNullable< T>: null과 undefined를 제외한 타입
    Parameters< T>: 함수 타입 T의 매개변수 타입들의 튜플타입을 구성
    ConstructorParameters< T>: 생성자 함수 타입의 모든 매개변수 타입을 추출
    ReturnType< T>: 함수 T의 반환 타입으로 구성된 타입을 생성
    Required< T>: T의 모든 프로퍼티가 필수로 설정된 타입을 구성
    일급 객체: 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체
    기본 매개변수: 함수에 주어진 인자의 수는 함수가 기대하는 매개변수의 수와 일치해야 한다.
    선택적 매개변수: js에서는 모든 매개변수가 선택적으로, 인수가 없다면 undefined
    기본-초기화 매개변수: ts에서는 값을 제공하지 않거나 undefined로 했을때 매개변수의 값 할당 가능
    나머지 매개변수: 매개변수의 수를 무한으로 취급한다.
    OOP: 컴퓨터 프로그램을 객체의 모임으로 파악하려는 프로그램이 패러다임
    public: 자유롭게 접근 가능, 기본적으로 정의
    private: 클래스 외부에서의 접근을 막는다.
    protected: 맴버가 포함된 클래스와 그 하위 클래스 외부에서의 접근을 막는다.
    getters & setter: 비공개로 설정하려는 속성은 private로 설정하고, 속성값을 읽고 수정하는 getter/setter 함수를 사용한다.
    readonly: 읽기만 가능한 속성을 선언하기 위해 사용한다.
    static: 전역맴버 선언, 객체마다 할당되지 않고 클래스의 모든 객체가 공유하는 맴버
    추상클래스: 다른 클래스들이 파생될 수 있는 기초 클래스, 직접 인스턴스화 할수 없다.

TypeScript 자료형

기본 자료형

Boolean

let isDone: boolean = false;

isDone = true;

console.log(typeof isDone); //boolean

let isOk:Boolean = true;

let isNotOk:boolean = new Boolean(true); //boolean은 기본개체이지만 Bollean은 래퍼개체로 오류가 발생한다.

Number

모든 숫자는 부동 소수점 값이다.

let decimal:number = 6;
let hex:number = 0xf00d; //16진수
let binary:number = 0b1010; //2진수
let octal:number = 0o744; //8진수
let notANumber : number = NaN;
let underscoreNum :number = 1_000_000;

String

let myName: string = "Mark";
myName = "Anna";

//Template String 행에 걸쳐있거나 표현식을 넣을 수 있는 문자열 ` backquote 기호와 ${} 를 통해 사용할 수 있다.

let fullName: string = "Mark Lee";
let age: number = 30;

let sentence: string = `Hello, my name is ${fullName}. 
i'll be ${age + 1} years old next month`;

console.log(sentence); // Hello, my name is Mark Lee. i'll be 31 years old next month

Symbol

new Symbol로 사용할 수 없다. 함수로 사용해서 타입을 만들어낼 수 있다.
고유하고 수정불가능한 값으로 만들어줘 주로 접근을 제어하는데 쓰는 경우가 많다.

const sym = Symbol();
const obj = {
[sym] : "value",
};
// obj["sym"] 접근이 불가능 하다.
obj[sym]

null & undefined

tsconfig.json에서 --strictNullChecks를 사용하면 null과 undefined는 void나 자기자신에게만 할당할 수 있다.

null타입은 null값만 가질수 있으며 런타임에서의 타입은 object이다.
undefined 런타임에서의 타입은 undefined이다.

let MyName: string = null; //Error
let u:undefined = null; //Error
let v:void = undefined;

let union: string | null = null;
union = 'mark';

참조 자료형

object

primitive type이 아닌 것을 나타내고 싶을 때 사용하는 타입이다.
(non-primitive type : number,string,boolean,bigint,symbol,null or undefined)

Array

자바스트립트에서 array는 객체이다.

let list1:(number | string)[] = [1,2,3,"4"];
let list2:Array<number> = [1,2,3]; //자주 사용은 안한다.

추가 자료형

Tuple

순서와type,길이가 맞아야한다.

let x:[string,number];
x = ["hello",10];
x = [10 , "mark"]; //error
x[2] = "world"; //error

const person:[string, number]=  ['mark', 20];
const [first, second] = person;

Any

어떤 타입이어도 상관없는 타입
컴파일타임에 타입 체크가 정상적으로 이뤄지지 않아 최대한 사용하지 않는게 좋다.

function returnAny(message: any): any {
console.log(message);
}

const any1 = returnAny("리턴은 아무거나");

any1.toString();

let looselyTyped: any = {};

const d = looselyTyped.a.b.c.d;

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

const c = leakingAny({ num: 0 }); //c = any
c.indexof("0")

Unknown

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

declare const maybe:unknown;

const aNumber:number = maybe;

if(maybe === true){
const aBollean:boolean = maybe; //true
// const aString:string = maybe;  error
}

if(typeof maybe === 'string'){
const aString:string = maybe // string
}

Never

모든타입에 subtype 이며, 모든 타입에 할당 할 수 있다.
never에는 그 어떤 것도 할당할 수 없다.(any도 불가능)
잘못된 타입을 넣는 실수를 막고자 사용한다.

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

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

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

  }
}
let a:string = 'hello';

if(typeof a !== "string") {
  //a에는 아무것도 할당할 수 없다.
}

declare const b:string|number;
if (typeof b !== "string") {
  	b //number
}

type Indexable<T> = T extends string ? T & {[index:string]:any} : never;

void

함수의 반환타입으로 사용된다.

function returnVoid (message:string):void{
console.log(message);
return; // return undefined
}
const r = returnVoid('리턴이 없다.'); //r = void 타입

유틸리티 타입

keyof

key값들을 Union형태로 받을 수 있음.

interface User {
  id: number;
  name: string;
  age: number;
  gender: "m" | "f";
}

type UserKey = keyof User; // "id" | "name" | "age" | "gender"
// keyof를 통해 User interface의 key값들을 Union 형태로 받음

const uk1:UserKey = ""; // [에러 발생]
const uk2:UserKey = "id"; // [에러 해결] User interface의 key값 중 하나 입력입력하세요

Partial< T>

모든 프로퍼티 → 옵셔널로 전환 (즉, 일부만 사용 가능)

없는 프로퍼티 사용 시 에러 발생

interface User {
    id: number;
    name: string;
    age: number;
    gender: "m" | "f";
}

// [에러 발생] 이유: age, gender 無
let admin1: User = { // 👈
    id: 1,
    name: "Bob",
};

// [에러 無]
let admin2: Partial<User> = { // 👈
    id: 1,
    name: "Bob",
};
/*
- 아래와 같음:
interface User {
    id?: number;
    name?: string;
    age?: number;
    gender?: "m" | "f";
} */

Required< T>

모든 프로퍼티 -> 필수로 전환

interface User {
    id: number;
    name: string;
    age?: number; // 👈 옵션
}

let admin: Required<User> = { // 👈
    id: 1,
    name: "Bob",
    age: 30, // 👈 Required<T>를 넣어서 age도 필수. 안 넣으면 에러 발생
}

Readonly< T>

모든 프로퍼티 → 읽기 전용으로 전환

interface User {
    id: number;
    name: string;
    age?: number;
}

// [기존] 처음 할당 후, 수정 가능
let admin1: User = {
    id: 1,
    name: "Bob",
};
admin1.id = 4;

// [적용] 처음 할당 후, 수정 불가
let admin2: Readonly<User> = {
    id: 1,
    name: "Bob",
};
admin2.id = 4; // ⛔ [id 에러 발생] 

Record<K,T>

K: key
T: type

예시1

[점수 객체 제작] 1~4학년의 점수 입력

  1. 적용전
interface Score {
    "1": "A" | "B" | "C" | "D";
    "2": "A" | "B" | "C" | "D";
    "3": "A" | "B" | "C" | "D";
    "4": "A" | "B" | "C" | "D";
}

const score: Score = {
    1: "A",
    2: "B",
    3: "C",
    4: "D",
}
  1. 리팩토링 1 | Record<K, T> 활용
    Record<키 값, 타입 값> → Record<학년, 성적>
const score: Record<'1'| '2' | '3' | '4', 'A' | 'B' | 'C' | 'D'> = {
    1: "A",
    2: "C",
    3: "B",
    4: "D",
}
  1. 리팩토링 2 | 타입(학년, 성적) 분리
    가독성 ↑
type Grade = '1' | '2' | '3' | '4' ;
type Score = 'A' | 'B' | 'C' | 'D' | 'F' ;

const score: Record<Grade, Score> = {
    1: "A",
    2: "C",
    3: "B",
    4: "D",
}

예시 2

적절한 값이 입력되었는지 체크하는 함수 제작

interface User {
    id: number;
    name: string;
    age: number;
}

function isValid(user: User) {
    const result: Record<keyof User, boolean> = {
        id: user.id > 0,
        name: user.name !== '',
        age: user.age > 0
    }
    return result
}
/*
[함수 기능]
user를 받아서 결과 객체(result) 제작 -> 조건 체크 -> 결과 리턴

[result 타입]
keyof User: result의 key는 User의 key
boolean: type은 모두 boolean */

Pick<T,K>

T타입에서 K프로퍼티만 골라서(Pick) 사용.

Omit<T, K> 반대

interface User {
    id: number;
    name: string;
    age: number;
    gender: "M" | "W"
}

const admin: Pick<User, "id" | "name"> = { // 👈 User에서 "id"와 "name"만 사용
    id: 0,
    name: "Bob"
}

Omit<T,K>

T타입에서 K프로퍼티만 생략(Omit)

Pick<T, K> 반대

interface User {
    id: number;
    name: string;
    age: number;
    gender: "M" | "W"
}

const admin: Omit<User, "age" | "gender"> = { // 👈 User에서 age & gender 제외한 나머지 사용
    id: 0,
    name: "Bob"
}

Exclude<T1,T2>

T1 타입들 중 T2타입과 겹치는 타입 제외

  • Omit과 차이

    	Omit: 프로퍼티들 제거.
    	Exclude: Type으로 제거.
// ex 1)
type T1 = string | number;
type T2 = Exclude<T1, number> // string. (T1에서 number를 제외)

// ex 2)
type T3 = string | number | boolean;
type T4 = Exclude<T3, number | string> // boolean

NonNullable< T>

null & undefined 제외한 타입 생성

type T1 = string | null | undefined | void;
type T2 = NonNullable<T1> // string | void
profile
코린이 입니당 :)

0개의 댓글