이 글은 KUIT Web 부원분들을 대상으로 쓴 글입니다.
DefinitelyTyped
DefinitelyTyped 프로젝트는 일종의 자원봉사 프로젝트
→ 여러 개발자들이 자발적으로 자바스크립트 모듈의 타입을 추가해주고 있다.
→ 이렇게 추가된 타입은 npm 을 통해 다운받을 수 있다.
→ IDE 에서 자바스크립트 모듈에 대한 타입 지원이 가능해진다.
출처: https://jake-seo-dev.tistory.com/209
@types 라이브러리
@types 라이브러리는 TypeScript를 사용하여 JavaScript 라이브러리를 사용할 때 필요한 타입 정의를 제공하는 라이브러리
→ JavaScript 라이브러리의 API에 대한 타입 정보를 TypeScript에 제공하여, TypeScript 컴파일러가 타입 검사를 수행할 수 있게 한다.
예를 들어, jQuery와 같은 써드 파티 JavaScript 라이브러리를 TypeScript에서 사용하려면, 해당 라이브러리의 각 기능에 대한 타입이 정의되어 있어야 한다.
-> 이때 @types 라이브러리를 사용하면, 해당 JavaScript 라이브러리의 API에 대한 타입 정의를 제공받을 수 있음
-> @types/jquery 같은 형태로 해당 라이브러리의 타입 정의를 설치할 수 있다.
never 타입
never를 사용하면 구조적 타이핑을 비활성화하고 사용자가 두 속성을 모두 포함하는 객체를 전달하지 못하도록 할 수 있다.
type VariantA = {
a: string
b?: never
}
type VariantB = {
b: number
a?: never
}
declare function fn(arg: VariantA | VariantB): void
const input = {a: 'foo', b: 123 }
fn(input) // ❌ 속성 'a'의 타입은 호환되지 않는다.
never 타입에는 값을 할당 할 수 없기 때문에, 함수에 올수 있는 다양한 파라미터에 제한을 거는 용도로 사용할 수 있다.
// 이 함수는 never만 사용 가능하다.
function fn(input: never) {
// do something...
}
declare let myNever: never
fn(myNever) // ✅
// never 이외에 다른 값은 타입 에러를 야기한다.
fn() // ❌
fn(1) // ❌
fn('foo') // ❌
declare let myAny: any
fn(myAny)
switch문과 if-else 문장 내부에서 철저한 일치를 보장할 수 있다.
function unknownColor(x: never): never {
throw new Error('unknown color')
}
type Color = 'red' | 'green' | 'blue'
function getColorName(c: Color): string {
switch (c) {
case 'red':
return 'is red'
case 'green':
return 'is green'
default:
return unknownColor(c) // 그 외의 string으 불가능하다.
}
}
에러를 발생시키거나 무한 루프를 도는 함수의 리턴타입으로도 쓰인다.
단 함수 선언문으로 그런 함수가 선언되었을 경우 그 함수의 리턴 타입은 void이고 함수 표현식으로 그런 함수가 선언되었을 때만 리턴타입이 never가 된다.
const errorFunc=()=>{
throw new Error("테스트 에러");
}
const infFunc=()=>{
while(true){}
}
// foo1, foo2는 never타입
const foo1=errorFunc();
const foo2=infFunc();
출처
https://ui.toast.com/posts/ko_20220323
https://yceffort.kr/2022/03/understanding-typescript-never
https://witch.work/posts/typescript-never-type
type과 interface의 차이
type은 모든 타입을 선언할 때 사용할 수 있고,
interface는 객체에 대한 타입을 선언할 때만 사용할 수 있다.
또한 확장 불가능한 타입을 선언하고 싶다면 type을 사용하면 되고,
확장 가능한 타입을 선언하고 싶다면 interface를 사용하면 된다.
출처
https://velog.io/@wlwl99/TypeScript-type과-interface의-차이
https://velog.io/@sagesrkim/TS-Interface-vs-Type-alias
리터럴 타입
아래 코드에서 Food에서 허용한 3개의 문자열 외에 다른 문자열을 사용하게 되면 에러가 발생한다.
type Food = "rice" | "noodle" | "meat";
const myFood1: Food = "rice";
const myFood2: Food = "aaa"; // Error: Type 'aaa' is not assignable to type 'Food'.
출처
https://choice91.tistory.com/161
ts-pattern
ts-pattern은 타입스크립트에서 패턴 매칭을 구현할 수 있게 해주는 라이브러리
→ 선언적이고 가독성 좋은 코드로 다양한 패턴을 처리 할 수 있습니다.
→ 디자인 시스템 컴포넌트의 구현에서 ts-pattern은 타입 안정성과 선언적 구현을 동시에 제공하여 개발자가 더욱 효율적으로 컴포넌트를 구축할 수 있게 해준다.
예시
import { match } from 'ts-pattern';
type Weather = 'sunny' | 'cloudy' | 'rainy' | 'snowy';
const getWeatherDescription = (weather: Weather): string => {
return match<Weather, string>(weather)
.with('sunny', () => 'It is a sunny day!')
.with('cloudy', () => 'It is a cloudy day.')
.with('rainy', () => 'It is raining outside.')
.with('snowy', () => 'It is snowing!')
.exhaustive();
};
const currentWeather = 'sunny';
const weatherDescription = getWeatherDescription(currentWeather);
console.log(weatherDescription);
출처
https://velog.io/@hhhminme/ts-pattern을-활용한-강력한-디자인-시스템-컴포넌트-만들기
JavaScript가 동적 언어이기 때문에 발생하는 문제
JavaScript는 동적 언어로, 이는 변수의 타입이 실행 시점에 결정된다는 것을 의미한다.
→ 이로 인해 코드 작성 시 자료형을 명시적으로 지정해 줄 필요가 없어, 프로그래머가 빠르게 코드를 작성 가능
하지만 이로 인해 생기는 문제점
타입 체크의 어려움
- JavaScript는 느슨한 타입의 동적 언어이기 때문에, 변수 생성 시 원시 변수의 타입을 미리 선언하지 않아도 됩니다. 하지만 많은 기능 명세서와 API가 오고 가는 대형 프로젝트에서 타입이 올바른지 체크하는 것이 굉장히 까다롭기 때문에 배포 시 예상치 못한 문제와 직면할 수 있습니다.
예상치 못한 타입 변환
- JavaScript는 동적 타입 언어로서, 문자열과 숫자를 더하는 등의 연산을 수행할 때, 어떻게든 이를 연산하기 위해 숫자 1을 문자열 '1’로 바꿔 ‘5’+'1’을 연산하게 됩니다. 이로 인해 예상치 못한 결과가 발생할 수 있습니다.
unknown과 any
any와의 눈에띄는 차이점은
unknown 타입은 any 타입 외의 어떤 타입에도 할당할 수 없다는 것
반면 any는 never를 제외한 모든것에 할당 가능
출처
https://xionwcfm.tistory.com/394
null과 undefined의 차이
null과 undefined는 이 변수가 어느 값을 가르키지 않는다는 것을 의미한다는 점에서는 비슷하다.
null은 어떤 값이 의도적으로 비어있음을 의미하는 표현이다.
undefined는 아예 어떤 값이 할당되지 않은 상태를 의미한다.
출처
https://medium.com/hcleedev/javascript-null과-undefined-그리고-optional-chaining-217ac24a2d2e
Type Assertion에서 as Number를 쓰고 연산을 하면 오류가 발생한다?
타입스크립트에서 as 키워드를 사용하는 것은 타입 단언(Type Assertion)이라고 한다.
이는 실제 데이터의 타입을 변경하는 것이 아니라, 컴파일러에게 해당 값이 특정 타입임을 알려주는 역할
→ as 키워드는 컴파일 시점에서만 작동하며, 런타임에서는 영향을 미치지 않는다.
예를 들어, ’as Number’ 를 사용하여 문자열을 숫자로 단언하면, 컴파일러는 해당 값을 숫자로 간주합니다.
→ 그러나 실제 런타임에서는 해당 값이 여전히 문자열이므로, 숫자에만 적용할 수 있는 연산(예: 덧셈)을 수행하려고 하면 에러가 발생!!
Interface에서는 value가 더 많은 property를 가지고 있어도 허용
Interface에서 최소 요구조건을 충족하는지 확인하는 것이므로 value가 더 많은 property를 가지고 있어도 허용한다.
유니온타입과 인터섹션타입의 차이
유니온타입의 경우 둘 중 하나의 규격대로 타입을 전달해도 문법 오류가 뜨지 않으나,
인터섹션타입의 경우 두개의 속성 타입을 모두 합한 규격을 전달해야 문법 오류가 뜨지 않는다.
출처
Enum과 객체 리터럴의 차이
Enum은 TypeScript에서만 지원하는 특별한 타입으로, 상수를 논리적으로 그룹화할 수 있다.
반면 객체 리터럴은 JavaScript의 기본 문법으로, 키-값 쌍을 가지는 구조다.
객체 리터럴은 타입스크립트에서 제공하는 타입 체킹을 받을 수 없으므로, 타입 안전성이 떨어진다.
반면 Enum은 TypeScript의 타입 체킹을 받으므로, 타입 안전성이 높다.
출처
'KUIT' 카테고리의 다른 글
[KUIT] 6주차 실습 코드 리팩토링 (0) | 2024.05.05 |
---|---|
[KUIT] 5주차 워크북 보충(React) (0) | 2024.05.03 |
[KUIT] 3주차 워크북 보충(JavaScript) (0) | 2024.04.05 |
[KUIT] 이벤트 캡처링과 버블링 (0) | 2024.04.01 |
[KUIT] 실행 컨텍스트와 this, 클로저, 호이스팅 (0) | 2024.03.30 |