궁금한게 많은 열아홉

목표

인터페이스의 개념을 이해하고, 어떻게 활용하는 지 알아보기

인터페이스(Interface)

상호 간에 정의한 약속 혹은 규칙이다. 객체 모양의 타입을 정의할 때 유용한 문법이고, 프레임워크에서는 주로 API응답, Props, 변수, 함수를 정의할때 자주 사용한다.

 

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

const vision: Person = { 
  name: '비전',
  age: 3
};

 

선택적 프로퍼티

인자를 넘길때 그 여부를 선택적으로 할 수 있도록 '?'를 활용해 명시해줍니다.

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

const vision: Person = { 
  name: '비전',
  age: 3,
  favoriteColor: 'blue'
};

const jin: Person = { 
  name: '진',
  age: 19,
};

읽기 전용 프로퍼티(readonly)

일부 프로퍼티들은 객체가 처음 생성될 때만 수정이 가능해야한다. 그 이후에는 변경이 불가하며 문법은 readonly 속성을 사용하면 된다.

 

interface Person {
  name: string;
  readonly age: number;
  favoriteColor?: string
}

const jin: Person = { 
  name: '진',
  age: 19,
};

jin.age = 20 // ERROR

 

readonly vs const

readonly const
속성을 위한 것 변수 참조를 위한 것
속성을 앨리어싱을 통해 변경될 수 있음 변수에 다른 값을 할당/대입할 수 없음

 

const studentNumber = 23; // 변수 참조
var phoneNumber: {
    readonly phoneNumber: number; // 속성의 경우
}

 

let foo: {
    readonly bar: number;
} = {
        bar: 123
    };

function iMutateFoo(foo: { bar: number }) {
    foo.bar = 456;
}

iMutateFoo(foo); // foo 인자가 foo 파라미터에 의해 앨리어싱됨
console.log(foo.bar); // 456!

 

초과 프로퍼티 검사

객체 리터럴은 다른 변수에 할당하게 되면, 인수를 전달할 때 초과 프로퍼티 검사를 진행한다. 따라서 인터 페이스에서 구현되지 않은 키를 전달하게 되면 에러가 발생한다. 조금 더 엄밀한 속성 검사를 진행하도록 한다.

 

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

function goToShopping(jin: Person): {name: string, area: string} {
	// ...
}

const jinPlan = goToShopping({name: "jin", area: "명동 신세계 백화점"});

 

추상화된 함수를 구현할 때 문자열 인덱스 서명을 사용할 수 있다.

 

함수 타입

함수의 타입을 정의할 때 우리는 주로 interface를 사용한다. 컴포넌트는 html을 리턴하는 함수이기 때문에 마찬가지로 props를 명확히 정의해야한다.

interface AppHeaderProps {
  headerTitle: string;
}

type AppHeaderProps = { headerTitle: string; }

function AppHeader(props: AppHeaderProps) {
  return (
    <h1>{props.headerTitle}</h1>
  );
}

인덱서블 타입

타입을 인덱스로 기술 할 수 있다. 인덱싱할 때 해당 반환 유형과 함께 객체를 인덱싱하는 데 사용할 수 있는 타입을 기술하는 인덱스 시그니처를 가진다.

 

import React from 'react';
import styled, { css } from 'styled-components';
import { Body2_3 } from 'styles/font';
import { theme } from 'styles/theme';

import { useTheme } from 'styled-components';
interface hashtags {
  [key: string]: any;
}

const HashtagColors: hashtags = {
  Restaurant: theme.colors.purple,
  Cafe: theme.colors.green,
  BirthCafe: theme.colors.blue,
};

const HashtagTexts: hashtags = {
  Restaurant: '맛집',
  Cafe: '카페',
  BirthCafe: '생일 카페',
};

export const Hashtag = ({ type, disabled, onClick }: any) => {
  const theme = useTheme();
  return (
    <HashtagContainer
      color={`${HashtagColors[type]}`}
      disabled={disabled}
      onClick={onClick}
    >
      <Body2_3 color={disabled ? theme.colors.gray02 : theme.colors.black}>
        #{`${HashtagTexts[type]}`}
      </Body2_3>
    </HashtagContainer>
  );
};

const HashtagContainer = styled.div<{ disabled: boolean }>`
  padding: 5px 15px 5px 10px;
  height: 30px;
  border-radius: 100px;
  background-color: ${({ color }) => (color ? color : '')};
  border: 1px solid var(--mono-black, #171717);

  ${({ disabled }) =>
    disabled &&
    css`
      cursor: pointer;
      border-radius: 100px;
      border: 1px solid var(--mono-gray-02, #dcdcdc);
      background: var(--mono-gray-01, #f4f4f4);
    `}
`;

 

참고자료

https://joshua1988.github.io/ts/guide/interfaces.html#%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4

https://typescript-kr.github.io/pages/interfaces.html

https://radlohead.gitbook.io/typescript-deep-dive/type-system/interfaces

https://tecoble.techcourse.co.kr/post/2022-11-07-typeAlias-interface/

 

profile

궁금한게 많은 열아홉

@jjin502

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!