[2021.08.23] TypeScript
📌 함수
- 매개변수의 우측에 콜론(:)과 매개변수의 타입을 정의
- return 값의 타입은 소괄호()우측에 타입을 정의
➡ formatDate의 매개변수 d는 Date 객체 타입을 받아야하고, return 값은 문자열이어야 한다
const formatDate = (d: Date): string => { // ✅
const year = d.getFullYear();
const month = d.getMonth() + 1;
const day = d.getDate();
return `${year}년 ${month}월 ${day}일`;
};
const today = formatDate(new Date());
console.log(today);
// lang의 경우 인자를 전달하지 않으면 "ko"라는 문자열 값이 할당
// delimiter는 물음표를 사용하여 선택적으로 인자 전달
let formatDate = (d: Date | number, lang = "ko", delimiter?: string): string => {
};
📌 새로운 타입 - 기본
💡 1. Any
- 어떤 타입이라도 모두 지정 가능하다
- JS로 컴파일된 코드를 보면 아무 타입도 지정되지 않은 원래의 JS 코드와 똑같다.
➡ any 타입을 쓰면? 타입스크립트 안 쓴 거와 같다 (any는 쓰지말자)
💡 2. void
- void는 any와는 반대로 어떤 타입도 없다는 뜻
- 보통 함수에서 반환값이 없는 경우 사용
💡 3. Enum
- 언제 사용 ? 상수로된 세트 값이 필요할 때
// Category라는 이름의 enum 타입을 정의한다
// Category의 enum 값에 Past, Pizza, Dessert 가 있다.
enum Category {
Pasta,
Pizza,
Dessert
}
let menuCategory: Category = Category.Pasta; // 0
// enum에 값 부여
enum Category {
Pasta = 'pasta',
Pizza = 'pizza',
Dessert = 'dessert'
}
let menuCategory: Category = Category.Pasta; // pasta
💡 4. union
- union타입은 여러 타입이 올 수 있을 때 사용
function formatDate(date: string | number | Date): string {
// 로직 생략
return `${year}년 ${month}월 ${day}일`
}
formatDate(20201028);
formatDate(new Date());
formatDate('20201028');
- 배열에 여러 타입의 값을 사용하고 싶을 때, 튜플을 쓸 때와 union을 쓸 때의 차이점
// union
let starNumberArr: (number | string)[] = [1, 2];
starNumberArr.push("3점");
// tuple
let starArr: [number, string] = [1, "1점"];
- union은 사용하고자 하는 타입 중에 하나만 있어도 가능.
튜플을 사용하면 배열의 요소에 정의한 타입이 모두 존재해야 한다.
💡 5. Type Alias
- 타입을 재사용하거나, 객체를 위한 타입을 정의할 때 많이 사용
// 방법은 아래처럼 type으로 정의하거나, interface로 타입을 정의하거나.
type ID = number | string;
//checkInfo 함수의 매개변수 info 객체를 위해 Info라는 타입을 만들기.
type Info = {
id: ID;
pw: string;
};
function checkInfo(info: Info) {
}
let id: ID = "1010";
checkInfo({ id, pw: "password" });
📌 타입추론 (Type Inference)
- 타입스크립트에서는 타입을 표기하지 않아도 타입스크립트 컴파일러가 변수에 할당된 값을 보고 타입을 추측
// ts 파일에서
let starArr = [1, 2, 3];
starArr.push('4점');
// 에러: Argument of type 'string' is not assignable to parameter of type 'number'.
// starArr는 숫자로만 이루어진 배열이 할당되어, number[] 타입으로 추론됨 => 에러 발생!
📌 인터페이스 (Interface)
-
state와 props의 타입을 정의하는데 주로 사용
-
readonly
,?
키워드 사용
// readonly는 읽기만 가능한 프로퍼티로, 값을 수정할 수 없습니다.
// 프로퍼티명 다음에 물음표(?)를 사용하면 해당프로퍼티를 추가해도 되고 안해도 됩니다.
interface Restaurant {
readonly name: string;
star: number;
address?: string;
}
const chroad3: Restaurant = {
name: "취향로3가",
star: 5,
};
chroad3.name = "chroad3"; // 에러: Cannot assign to 'name' because it is a read-only property.
chroad3.star = 4;
const sipboon: Restaurant = {
name: "십분의일",
star: 5,
address: "을지로3가",
};
extends
사용 : 기존에 정의된 인터페이스를 확장
interface BasicInfo {
name: string;
star: number;
}
const sipboon: BasicInfo = {
name: "십분의일",
star: 5,
};
// extends
interface DetailInfo extends BasicInfo {
address: string;
phone: string;
position: number[];
}
const chroad3: DetailInfo = {
name: "취향로3가",
star: 5,
address: "을지로3가",
phone: "123-456-7890",
position: [37.565496, 126.99142],
};
- 교차타입 :
type
사용
➡ 합쳐서 새로운 인터페이스를 만드는 것은 아니고,& 기호
를 사용하여 기존에 정의했던 인터페이스를 합쳐서 새로운 타입을 만드는 것
interface BasicInfo {
name: string;
star: number;
}
interface DetailInfo {
position: number[];
}
type Info = BasicInfo & DetailInfo;
📌 타입호환성 (Type Compatibility)
Q. v1, v2 둘 중에 어떤 라인이 에러가 날까?
function getStar(score: number | string, scoreNum: number) {
const v1: number = score;
const v2: number | string = scoreNum;
}
- (정답) v1
- 만약 score가 문자열로 전달됐다면 string 타입이 되기 때문에 v1 타입인 number에 포함되지 않는다.
- scoreNum 매개변수는 숫자타입이기 때문에 v2타입인 number, string 둘 중에 하나 포함되므로 타입이 호환된다.
📌 제네릭 (Generic)
- 타입을 정의할 때 특정 타입으로 고정된 것이 아니라,
내가 원하는 타입을 자유롭게 지정해서 계속 사용하고 싶을 때 제네릭을 사용 - 제네릭은 타입을 마치 재사용할 수 있는 변수처럼 취급해서 여러 군데에서 사용하고 싶을 때 사용
- 제네릭은 함수명 우측에 화살표괄호(<>)로 감싼다.
- T는 특별한 의미가 없는 변수명 같다고 생각하면 되는데,
제네릭을 사용할 때 보통 대문자 T를 자주 사용한다.
(내가 원하는 이름으로 자유롭게 작성할 수 있다)
function makeArr<T>(el: T): T[] {
return [el];
}
makeArr<number>(1); // 1 number[]
makeArr<string>("1점"); // 2 string[]
makeArr<boolean>(true); // 3 boolean[]
- 제네릭 타입을 명시하지 않아도 컴파일러는 전달되는 인자값을 통해 타입을 추론하여 T의 타입을 결정
- 아래 코드는 훨씬 간결하고 가독성이 높아졌지만, 추후 유지보수를 위해서나 더 복잡한 예제의 예상치 못한 오류를 위해 제네릭 타입을 정확히 써주는게 좋을 때도 있다.
makeArr(1);
makeArr("1점");
makeArr(true);
📌 리액트를 위한 타입스크립트
💡 객체 타입을 정의하는 방법은 object
, interface
, type alias
세 가지!
- object 타입 → 타입을 재사용할 수 없으며, 프로퍼티가 많을 수록 가독성이 좋지 않다
- state나 props를 정의할 때 interface나 type을 사용하는 것이 좋다.
- type과 interface는 확장, 병합 가능성이라던지 선언 등의 차이점이 있어서 상황에 따라 적절하게 사용하면 되지만, 타입스크립트 공식 문서에는 type보다 interface를 사용하라고 되어있다.
💡 함수형 컴포넌트의 타입을 선언하는 두 가지 방법
1. 리액트의 FC 타입 사용
interface StarsProps { // prop 타입 정의
star: number;
}
const Stars: React.FC<StarsProps> = ({ star }) => { //
return (
<div>
{makeStars(star)}
</div>
)
}
2. 일반적인 함수정의 방식
interface StarsProps { // prop 타입 정의
star: number;
}
const Stars = ({ star }: StarsProps): JSX.Element => { //
return (
<div>
{makeStars(star)}
</div>
)
}
💡 Hooks
* useState
- 특별히 타입을 명시하지 않더라도 타입추론을 통하여 타입이 지정된다.
const [like, setLike] = useState(false);
useState<boolean>(initialState: boolean | (() => boolean))
: [boolean, Dispatch<SetStateAction<boolean>>]
- state의 초기값을 설정할 때 null을 사용하면? 유니온 타입을 사용하여 타입을 명시
// 유니온 타입으로 전달
const [like, setLike] = useState<boolean | null>(null);
- state에 객체가 포함된 경우, 자세한 프로퍼티 타입을 알 수 있도록 아래와 같이 정의
// state 타입 정의
interface Comment {
comment: string;
username: string;
date: string;
star: number;
}
const [comments, setComments] = useState<Comment[]>([]);
* useRef
- useState처럼 타입을 명시하지 않아도 된다.
- 만약 코드의 명확성을 위해서 타입을 정의하고 싶은 경우, 아래와 같이 ref의 태그에 맞는 제네릭을 넘겨주면 된다.
const reviewRef = useRef<HTMLDivElement>(null);
//로직 생략
return (
<>
<Review reviewTextRef={reviewRef} />
<div ref={reviewRef}>
리뷰
</div>
</>
)
💡 Event Handler
- 이벤트 핸들러 함수의 이벤트 매개변수에는 특별한 타입이 필요하다
- 물론 매개변수에 타입을 명시하지 않아도 오류는 나지 않지만, 정확히 어떤 종류의 이벤트이고, 어느 태그에서 발생하는 것인지 써주는 것이 좋다.
- 일반적으로 타입 이름은 "이벤트타입Event"으로 ChangeEvent, FormEvent, TouchEvent, FocusEvent, KeyboardEvent, MouseEvent, DragEvent 등이 있다.
💡 전역 변수
- window에 외부 라이브러리 변수를 추가하려면 아래와 같이 해당 라이브러리에서 사용하는 전역 변수명을 추가하면 된다.
declare global {
interface Window {
kakao: any;
}
}
Author And Source
이 문제에 관하여([2021.08.23] TypeScript), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@daeun-react/2021.08.23-TypeScript저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)