[TypeScript] 인터페이스(Interface)
목표
인터페이스의 개념을 이해하고, 어떻게 활용하는 지 알아보기
인터페이스(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/