[TS] typescript 공부하기

해달·2022년 3월 12일
0

인프런 캡틴판교님의 타입스크립트 입문 - 기초부터 실전까지 강의를 들으며 공부한 내용입니다.

type-basic

// 문자열
const str: string = 'hello';

// 숫자
const num: number = 10;

// 배열
const arr: Array<string> = [];
arr.push('hi');

// 배열 - 리터럴 적용
const items: string[] = [];
// items.push(10);

// 튜플
const address: [string, number] = ['판교', 40];

// 객체
const obj: object = {};
// obj.a = 10;

// 타입 객체
const person: { age: number; name: string } = { age: 100, name: 'Capt' };
person.age = 101;

// 진위값
let isLogin: boolean = false;

interface

interface User {
  age: number
  name: string
}

const seho: User = {
  age: 33,
  name: '세호',
}

// 함수에 인터페이스 활용
// 인자에다가 User라는 interface를 쓴다는 것은 특정형식을 준수하는 데이터만 받겠다고 정의를 한 형태
// parameter에다가 인터페이스를 정의하고 함수를 호출할 때 인자가 파라미터에 정의한 인터페이스의 규칙을 잘 따르는지까지 확인해주는 것이 타입스크립트의 역할이고
// 인터페이스의 장점이다

function getUser(user: User) {
  console.log(user)
}

const sun = {
  name: '해',
  age: 100,
}

getUser(sun)

//함수의 스펙(구조)에 인터페이스를 활용
interface SumFunction {
  (a: number, b: number): number
}
// 인자 a와 b는 number 타입이고 반환값의 타입도 number다

let sum2: SumFunction

sum2 = function (a: number, b: number): number {
  return a + b
}

// sum2를 선언하면서 interface를 지정해주고 sum2에 함수를 지정할 때 이전에 지정했던 인터페이스의 타입과 동일하게 설정을 해주어야한다

// 인덱싱
interface StringArray {
  [index: number]: string
}

var arr = ['a', 'b', 'c']
arr[0] //'a'

//인터페이스 확장
// 디벨로퍼 중복되는 값들을 다른 인터페이스가 가지고있다고 하면 갖고있는 속성과 타입을 상속을 받을 수 있다

interface Person {
  name: string
  age: number
}

interface Developer extends Person {
  language: string
}

var captain: Developer = {
  language: 'ts',
  age: 100,
  name: '캡틴',
}

Type Aliases (타입 별칭)

특정 타입이나 인터페이스를 참조할 수 있는 타입 변수

// string type사용
const name: string = 'capt';

// 타입 별칭을 사용할 때
type MyName = string;
const name: Myname = 'capt';

type vs interface

interface Person_I {
  name: string
  age: number
}

type Person_T = {
  name: string;
  age: number;
}

var sehoo: Person_I = {
  name: '세호',
  age: 30
}

interface와 type의 차이

타입은 extends 불가능
interface extends는 가능
TS 공식문서에서 interface 사용을 추천


유니온 Type (|)

or을 이용하여 여러개의 타입 지정하기

function logMessage(value: string | number) {
  console.log(value);
}

function logMessage2(value: string | number) {
  if(typeof value === 'number'){
    value.toLocaleString();
  }
}

이러한 방식은 타입가드라고 부를 수 있다
타입 가드 : 특정 타입으로 타입의 범위를 좁혀나가는(필터링 하는)과정

interface Developer {
  name: string;
  skill: string;
}

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

function askSomeone(someone: Developer | Person){
  someone.name
}

인터페이스같은 특정 구조체를 여러개 유니온 타입으로 설정할 시에는 공통 된 속성만 접근할 수 있다
위와 같은 경우에는 name 속성에만 접근이 가능하다


인터섹션 (&)

function askSomeone(someone: Developer & Person){
  someone.name
}

askSomeone({name: 'name', skill : 'skill', age: 1});

& 로 연결할 경우 포함하는 새로운 타입을 만들게 된다


이넘(Enums)

특정 값들의 집합을 의미하는 자료형

숫자형 이넘

enum Shoes{
  Nike,
  Adidas
}

var myShoes = Shoes.Nike;

console.log(myShoes); // 0

값에 특정값을 할당하거나 초기화를 하지 않는다면
기본값들은 자동으로 숫자로 증가하게 됨

Nike = 10
Adidas // 11 자동증가 됨

문자형 이넘

enum Shoes{
  Nike = '나이키',
  Adidas = '아디다스'
}

var myShoes = Shoes.Nike;
console.log(myShoes); // 나이키
//활용 예제
enum Answer{
  Yes = 'Y',
  No = 'N',
}

function askQuestion(answer: Answer){
  if(answer === Answer.Yes)
    ...
}

enum으로 제공되는 값만 적용해서 비교할 수 있다(ex:드롭다운)


제네릭

function getText<T>(text: T): T {
  return text;
}

getText<string>('hi');


function getText<string>(text: string): string {
  return text;
}

함수를 호출하면서 전달하는 타입의 값이 지정해준 제네릭자리에 다 들어간다
파라미터의 타입을 지정하면서 넘겨준다


문제가 될 수 있는 코드



function logText(text: string) {
  console.log(text);
  return text;
}

function logNumber(num: number) {
  console.log(num);
  return num;
}

같은 작업을 하는 코드를 타입을 다르게 받는다는 이유로 위와 같이 작성하게 된다면
유지보수 측면에서도 굉장히 안좋은 코드로 취급된다


인터페이스에 제네릭을 선언하는 방법

interface Dropdwon {
  value: string;
  selected: boolean;
}

const obj_1: Dropdwon = {value: 'abc', selected: false};


interface GenericDropdwon<T>{
  value: T;
  selected: boolean;
}

const obj_2: GenericDropdwon<string> = {value: 'abc', selected: false};

유니온 / 제네릭 방식의 차이


// 유니온방식

function createDropdownItem(item: DropdownItem<string> | DropdownItem<number>)  

 emails.forEach(function (email) {
  const item = createDropdownItem(email); 
});


// 제네릭방식 

function createDropdownItem<T>(item: DropdownItem<T>) 

 
emails.forEach(function (email) {
	const item = createDropdownItem<string>(email);
}

제네릭의 타입 제한

제네릭의 타입 제한 1 - (타입에 대한 힌트주기)
ts입장에서는 어떤 타입이 알수가 없기때문에 length라는 프로퍼티에대한 에러가 난다

function logTextLength<T>(text: T): T{
  console.log(text.length);
  return text;
}


//함수 안에서는 제네릭의 타입이 배열이라는것을 알고 있기 때문에 배열이라 가정을 하고 그 외 속성이나 API를 제공한다
function logTextLength<T>(text: T[]): T[]{
  console.log(text.length);
  text.forEach((el) => {
    console.log(el)
  })

  return text;
}

제네릭 타입 제한 2 - 정의된 타입 이용하기 (하위호환)

interface LengthType {
  length: number;
}

function logTextLength<T extends LengthType>(text: T): T{
  text.length;
  return text;
}

logTextLength({length: 10});

제네릭 타입제한 3 - keyof
이미 지정해놓은 타입 중에서만 어떤것을 받을지 제한하기

interface ShoppingItem {
  name: string;
  price: number;
  stock: number;
}

// ShoppingItem에 있는 키 중에 한가지가 제네릭이 된다 
// 파라미터로는 name, price, stock 중 한가지가 된다
function getShoppingItemOption<T extends keyof ShoppingItem>(itemOption: T): T{
  return itemOption;
}
getShoppingItemOption('name')

0개의 댓글

관련 채용 정보