타입스크립트에 대해 설명하는 것을 목적으로 하는것이 아닌, 개인적으로 공부한 내용을 정리하기 위해 작성한 글이다. 그렇기때문에 제외된 내용이 있을 수 있고 순서가 맞지 않을 수 있다는 점 양해바란다.
타입스크립트를 사용하면, 타입을 정의함으로써 에러를 사전에 방지할 수 있고 타입별 관련 함수를 자동완성 시켜주어(IDE 지원) 개발의 생산성을 향상 시킬 수 있다.
이러한 이유들로 대규모 프로젝트에서는 타입스크립트를 필수로 사용하고 있으며 요즘 많은 곳에서도 도입하고있다.
React 에서 TypeScript 를 사용 할 예정이라 CRA로 프로젝트를 생성한다.
npx create-react-app learn-ts --template typescript
권한관련 에러가 발생해 해당 폴더의 소유권을 변경했다
sudo chown -R $USER ./learn-ts
key1?: 타입
으로 작성 가능하다.[key: string]: string
으로 작성 가능하다. type Member ={[key: string]: string}
let jae: Member={name:'jae', age: '31'}
둘 이상의 타입을 |
로 연결해 or 조건을 갖는 타입이다.
: string | number // 문자와, 숫자
: (string | number)[] // 문자와 숫자를 요소로 둘 수 있는 배열
튜플은 배열의 길이와 요소의 타입을 지정한다.
type Member = [number, string]
let kim: Member = [32, 'jae']
변수에 특정 값을 지정해주는 타입이다.
// 변수
let sns: 'kakao' | 'google' // kakao와 google만 허용한다.
//함수
const testFn = (a: 'hello'): 1|0 =>{
return 0 // 1이나 0만 리턴할 수 있다.
}
var person = {name: 'kim'}
const testFn = (name: 'kim'): string =>{
return `안녕하세요 ${name}님`
}
testFn(person.name) // error!!
testFn의 인자인 name의 타입은 'kim' 으로 지정되어 있는데
person.name 은 자료형이 'kim' 이지 타입은 'string' 이므로 에러가 발생한다.
let 변수: 타입 = 타입에 맞는 값;
let num: number = 0;
let str: string = 'abc';
let arr: string[] = ['a', 'b', 'c']
let obj: {name: string, age: number} = {name: 'jae', age: 29}
...
타입스크립트에서는 함수의 인자를 필수값으로 간주한다. 따라서, 인자의 갯수가 맞지 않으면 에러가 발생한다. 선택적으로 인자를 받기 원하면 ?
를 붙여주면 된다.
const 함수명 = (인자1: 타입, 인자2?: 타입): 함수타입=>{
}
const testFn = (a: number, b?: number): number =>{
return a+b;
}
type을 변수로 만들어 사용할 수 있으며, 이 때 첫 글자는 대문자로 시작한다. 타입 변수들을 Union 할 때 사용할 수 있다
type Member = {
[key :string] : string
} // alias
let kim : Member ={
name: 'jae',
age: '31'
}
---------------------------
type Name = string
type Age = number
type Person = Name | Age // 이렇게 Union이 가능하다.
let person :Person = 'kim'
// object의 경우 '&'를 사용해서 Union 해주어야 한다.
type PositionX = {x :number}
type PositionY = {y :number}
type Position = PositionX & PositionY // {x :number, y :number}
함수의 type에 alias 를 적용하는 방법은 조금 다르다.
type 타입명 = (a?: 타입) => 타입
type FunType = (a?: string) => number
const testFn: FunType = (a) => {
return 0;
}
testFn('abc') // 0
객체의 타입(object)을 정의할 때 유용하게 사용되며, 상속이나 확장에 있어 장점이 있다.
interface Hashtag {
tagId?: number,
title: string,
count: number
}
let hashTag = {
title: '인기검색어',
count: 13
}
const getHashTag = (tag: Hashtag) =>{
return tag
}
getHashTag(hashTag) // {title: '인기검색어', count: 13}
트위터 클론 코딩에서 사용한 인터페이스 예시를 하나 가져와봤다.
// /src/model/post.ts
interface UserID {
userId: string,
}
interface PostImage {
link: string,
imageId: number,
Post?: Post
}
export interface Post {
postId: number;
User: User;
content: string;
createdAt: Date;
Images: PostImage[],
Hearts: UserID[],
Reposts: UserID[],
Comments: UserID[],
_count: {
Hearts: number,
Reposts: number,
Comments: number,
},
Original?: Post; // 재게시
Parent?: Post; // 답글
}
💡 Type 과 Interface의 차이
// interface // type interface User { | type User { name: string, | name: string, age: number | age:number } | }
두 방법 모두 사용 가능하지만, Interface 의 경우 확장이 가능하다는 장점이 있다. 가능하면 type 보다는 Interface를 사용하는 것 이 좋다.
읽기전용으로 선언된 속성은 처음 객체를 생성한 이후 변경이 불가능
하다.
interface PostImage {
link: string,
Post?: Post,
readonly imageId: number,
}
let postImage: PostImage = {
link: 'https://~~~~~',
imageId: 1
}
...
postImge.imageId = 3 // error!!
객체타입 외에도 함수에서도 사용 할 수 있다.
interface login{
// (인자1: 타입, 인자2: 타입): 리턴 타입
(username: string, password: string): boolean;
}
const loginUser: login = (username, password) =>{
return true or false
}
loginUser('tester', 5837264) // error!!
loginUser('tester', 'admin11')
타입을 함수나 인터페이스의 파라미터로 넘겨 사용하는 문법이다. 즉 사용자가 상황에따라 타입을 정할 수 있다.
// 함수에서 사용
const getSomething = <T>(prop: T): T =>{
return prop
}
getSomething<string>('hi')
getSomething<number>(30)
getSomething<boolean>(true)
// 인터페이스에서 사용
interface Person<T> {
name: string,
age: T
}
const kim: Person<number> ={
name: 'jae',
age: 31
}
//타입에 사용
type User<T> ={
name: string,
age: T
}
const kim: User<number> = {
name: 'jae',
age: 30
}
변수를 선언하거나 초기화 할 때 타입이 정해지는 것을 말한다. 실무에서는 모든 변수에 타입을 명시하지 않고, 타입추론을 많이 사용한다.
const [item, setItem] = useState(10) -> number
API 에서 받아오는 응답 데이터의 타입을 정의하는 것이다. async & await 은 Promise
객체이므로 제네릭으로 타입을 선언해준다.
// api 정보
url : https://jsonplaceholder.typicode.com/todos
data:
[
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
},
{
"userId": 1,
"id": 2,
"title": "quis ut nam facilis et officia qui",
"completed": false
},
{
"userId": 1,
"id": 3,
"title": "fugiat veniam minus",
"completed": false
}
]
// script
interface Todo{
userId: number;
id: number;
title: string;
completed: boolean
}
const apiUrl = "https://jsonplaceholder.typicode.com/todos"
async function fetchTodos(): Promise<Todo[]>{ // 제네릭 타입 선언
const response = await fetch(apiUrl);
const data = await response.json();
return data;
}
fetchTodos().then(todoList =>{
console.log('todo[0]: ', todoList[0]) // delectus aut autem
})
Chat GPT 질의를 통해 데이터 타입을 빠르게 정의할 수 있다. 위의 예제를 활용해보겠다.
response data를 가지고 GPT에게 물어보면
아주 친절하게 알려준다.