Typescript 알아가기 (1)

기멜·2021년 12월 28일
1

Typescript

목록 보기
2/2

타입스크립트 부수기!

JS문법 그대로 TS에서 사용가능

타입스크립트 이용방법

  • nodejs 최신버전 설치
  • 터미널에 npm install -g typescript
  • tsconfig.json 만들고
  • 어쩌구.ts파일에 코딩시작
  • 터미널에 tsc-w 해둔 채로

변수 만들기

변수에 타입지정가능

let 이름:string = 'kim';
이름 = 123; //에러가 남 string타입만 올 수 있기 때문에

변수에 [실드]를 씌우는 것입니다.

let age:number = 30;
let isAdult:boolean = true;
let a:number[] = [1,2,3];
let a2:Array<number> = [1,2,3]; //이렇게 써도 됨

let week1:string[] = ['mon','tue','wed'];
let week2:Array<string> = ['mon','tue','wed'];

타입스크립트 갓 배운 사람들은 모든 곳에 다 타입지정을 한다.
그런데 타입지정은 원래 자동으로 됩니다. 타입지정 문법 생략가능

let 회원들 = 'park' //이렇게 하면 무조건 회원들:string 이 되어있는것입니다.

문자 or 숫자 들어올 수 있는 변수 만들기

let 회원 :number | string = 123; //문자 또는 숫자 들어갈 수 있음

Union Type 이라고 합니다.

숫자 or 문자가 가능한 array/object 타입지정은?

let 회원들 :(number | string)[] = [1,'2',3]; //숫자 또는 문자 입력가능
let 회원들 : number | string[] = [1,2,3]; //이렇게 쓰면 숫자(1,2,3), ['1','2','3'] 가능하다는 뜻.
let 오브젝트 :{ a :string | number } = { a :'123' }

any or unknown

any

let 이름 :any;
이름 = 123;
이름 = [];

모든 자료형을 허용해주는 대신 타입스크립트를 쓰는 의미가 없어집니다.
이건 타입실드 해제문법입니다. '이름'이라는 변수의 실드를 해제시켜라 라는 뜻입니다.
그래서 타입관련 버그가 나도 잡아주질 않습니다.

unknown

let 이름 :unknown;
이름 = 123; 
이름 = {};

모든 자료형을 허용해줍니다. any와 유사해보입니다.

하지만 unknown타입이 any보다 안전한 이유는

let 이름 : unknown;
이름 = 123; 
이름 = {};

let 변수1 :string = 이름; //지금 이름이라는 변수는 {}(object)이기때문에 오류가 난다.
let 이름 : any;
이름 = 123; 
이름 = {};

let 변수1 :string = 이름; //하지만 any를 쓰는 순간 모든 실드는 해제됩니다.

함수

function 함수(x :number) : number {
  return x * 2
}
함수(6)

함수는 파라미터, return값 타입지정 가능
함수에서 void타입 활용가능. 어떤값도 return하고 싶지 않을 때 (return이 없을 경우)
실수로 뭔가 return하는 걸 사전에 막을 수 있습니다.

파라미터가 옵션일 경우엔
파라미터변수?:타입

function 함수(x? :number) :void {
}
함수()

?연산자는 들어올 수도 있다~ 라는 뜻이긴 한데
변수? :number는
변수 :number | undefined 와 같습니다.

❗️예를 들어 이런 함수가 있다고 생각해봅시다❗️
함수에 숫자 또는 문자를 집어넣으면 + 1 해주는 함수입니다.

function 내함수(x :number | string){
   return x + 1  //에러남 
}

근데 이런 에러가 납니다.
Operator '+' cannot be applied to types 'string | number' and 'number'
string | number 같은 union type 에는 일반적으로 조작을 못하게 막아놔서 그렇습니다.

이런 메세지를 보면
1. 타입을 하나로 Narrowing 해주거나
2. Assert 해주거나 둘 중 하나 해주면 됩니다.

Type Narrowing
if문 등으로 타입을 하나로 정해주는 것을 뜻합니다.

function 내함수(x :number | string){
  if (typeof x === 'number') {
    return x + 1
  } 
  else if (typeof x === 'string') {
    return x + 1
  }
  else {
    return 0
  }
}

if문과 typeof 키워드로 현재 파라미터의 타입을 검사해서
"이게 'number'타입일 경우 이렇게 해주세요~"
"이게 'string'타입일 경우 이렇게 해주세요~"
이렇게 코드를 짜야 정상적으로 사용이 가능합니다.
타입스크립트는 타입이 애매한 걸 싫어해서 귀찮아도 해야합니다.
타입이 확실하지 않을 때 생기는 부작용을 막기위한 장치라고 보시면 됩니다.

그런데 또 함수 안에서 if문을 쓸 때 마지막에 else {} 이게 없으면 에러가 납니다.
return 하지않는 조건문이 있다면 나중에 버그가 생길 수 있어서 에러를 내주는 것입니다.

assertion 문법

function 내함수(x :number | string){
  let array :number[] = [];
  array[0] = x as number;
}
내함수 

interface란?

let user:object;

user = {
  name : 'xx',
  age : 30
}
console.log(user.name)//이렇게 하면 오류가 납니다.

오류가 나는 이유: object에 특정 속성값에 대한 정보가 없기때문에..! 이렇게 프로퍼티를 정해서 객체를 표현하고자 할 때는 interface를 사용합니다.

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

let user : User = {
  name : 'xx',
  age : 30
}

console.log(user.age) //에러가 발생하지 않습니다.

readonly

읽기전용입니다. 값의 접근은 할 수 있지만 수정은 불가능 합니다.

interface User {
  name : string;
  age : number;
  gender? : string;
  readonly birthYear : number;
}

let user : User = {
  name : 'xx',
  age : 30,
  birthYear : 2000, 
}

user.age = 10;
user.gender = "female"
user.birthYear = 1990; //오류가 납니다. 

console.log(user.age)

birthYear에서 오류가 나는건 readonly가 읽기 전용 속성이어서 그렇습니다. 수정을 못한다는 얘기입니다.
생성할 때만 할당 가능하고 이후에는 수정하지 못합니다.

함수 오버로드

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

function join(name: string, age: string): string;
function join(name: string, age: number): User;
function join(name: string, age: number | string): User | string {
  if (typeof age === "number") {
    return {
      name,
      age,
    };
  } else {
    return "나이는 숫자로 입력해주세요.";
  }
}

const sam: User = join("Sam", 30);
const jane: string = join("Jane","30");

함수 오버로드를 해주어서 에러를 잡습니다.

Literal Types

const userName1 = "Bob";
let userName2 = "Tom";

const로 정의한 userName1은 "Bob"만 쓸 수 있는데,
let으로 정의한 userName2는 어떤 string이던 가능하다.

const userName1 같은 타입을 문자열 리터럴 타입이라고 부릅니다.

Union Types


interface Car {
  name: "car";
  color: string;
  start(): void;
}

interface Mobile {
  name: "mobile";
  color: string;
  call(): void;
}

function getGift(gift: Car | Mobile) {
  console.log(gift.color);
  if (gift.name === "car") {
    gift.start();
  } else {
    gift.call();
  }
}

마지막에 if문을 사용했는데 검사할 항목이 많으면 switch를 쓰는 것이 좋습니다.

Intersection Types

interface Car {
  name: string;
  start(): void;
}

interface Toy {
  name: string;
  color: string;
  price: number;
}

const toyCar: Toy & Car = {
  name : "타요",
  start() {},
  color: "blue",
  price: 1000,
};

&를 사용해서 두 가지 타입을 합칠 수도 있습니다.
그대신 안에는 두가지 타입에 있는 모든 걸 다 적어야 에러가 나지 않습니다.

Generic

제네릭을 이용하면 클래스나 함수, 인터페이스를 다양한 타입으로 재사용할 수 있습니다. 선언할 때는 그냥 타입 파라미터만 적어주고 생성하는 시점에서 사용하는 타입을 결정하는 겁니다.

function getSize<T>(arr: T[]): number {
  return arr.length;
}

const arr1 = [1,2,3];
getSize<number>(arr1); //3

<T>를 타입파라미터라고 합니다.
어떤 타입을 전달받아서 이 함수에서 사용할 수 있게 합니다.

사용하는 쪽에서 타입을 결정해줍니다.

interface Mobile<T> {
  name: string;
  price: number;
  option: T;
}

const m1: Mobile<object> = {
  name: "s21",
  price: 1000,
  option: {
    color: "red",
    coupon: false,
  },
};

const m2: Mobile<string> = {
  name: "s20",
  price: 900, 
  option: "good",
};

option에서 어떤 데이터를 사용할지 모르기 때문에 이럴 때 제네릭을 쓸 수 있습니다.

keyof

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

type UserKey = keyof User; // 'id' | 'name' | 'age' | 'gender'

const uk:UserKey = "id";

Partial<T>

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

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

let admin: Partial<User> = {
  id: 1,
  name: "Bob",
  job: "" // 에러납니다. User에 없기때문이죠.
};

모든걸 옵션으로 바꿔줌.

Required<T>

모든 걸 필수로 바꿔줌.

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

let admin: Required<User> = {
  id: 1,
  name: "Bob",
  age: 30; //이걸 안적으면 오류가 남. 모두 필수로 바꼈기때문에
};
profile
프론트엔드 개발자를 꿈꾸는 도화지 위를 달리는 여자

0개의 댓글