Closed moonheekim0118 closed 2 years ago
ํ๋ ๋ ๐ ํ๋ ๋ ๐ (๋๋ฆ ์ ๋ ฅ์ง์ฃผ ์ค)
interface Crew {
name: SophiaName | SellyName | HopeName;
emoji: SophiaEmoji | SellyEmoji | HopeEmoji;
}
name์ด SophiaName์ด๋ฉด์ emoji๊ฐ SellyEmoji์ผ ์๋ ์๋ค. ์ด๋ฐ ์กฐํฉ์ ํ์ฉํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฝ๊ณ ์ธํฐํ์ด์ค๋ฅผ ๋ค๋ฃจ๊ธฐ ์ด๋ ค์์ง๋ค โ ๊ฐ๊ฐ์ ํ์ ์ ๊ณ์ธต์ ๋ถ๋ฆฌ๋ ์ธํฐํ์ด์ค๋ก ๋์
interface SophiaCrew {
name: SophiaName;
emoji: SophiaEmoji
}
์ด๋ฐ ํํ๋ก ์ ์ํ๋ฉด ์์ฑ์ด ์๋ชป๋ ์กฐํฉ์ผ๋ก ์์ด๋ ๊ฒฝ์ฐ๋ฅผ ๋ฐฉ์งํ ์ ์๋ค.
ํ๊ทธ๋ ์ ๋์จ ์ฌ์ฉํ๊ธฐ. type์ด๋ผ๋ ํ๋๋ฅผ ์ถ๊ฐํ์ฌ ๊ตฌ๋ถํ๊ธฐ. ํ๊ทธ๋ฅผ ์ถ๊ฐํ์ฌ ๋ฐํ์์ ์ด๋ค ํ์ ์ด ์ฌ์ฉ๋๋์ง ํ๋จํ ๋ ์ฌ์ฉ๋๋ค. ์ด๋ฌ๋ฉด ํ์ ์คํฌ๋ฆฝํธ๊ฐ ์ฝ๋์ ์ ํ์ฑ์ ์ฒดํฌํ๋๋ฐ ๋์์ด ๋๋ค.
interface SophiaCrew {
type: 'sohpia'
name: SophiaName;
emoji: SophiaEmoji
}
interface SellyCrew {
type: 'selly'
name: SellyName;
emoji: SellyEmoji
}
interface HopeCrew {
type: 'hope'
name: HopeName;
emoji: HopeEmoji
}
type Crew = SophiaCrew | SellyCrew | HopeCrew;
์ฌ๋ฌ๊ฐ์ ์ ํ์ ํ๋๊ฐ ๋์์ ๊ฐ์ด ์๊ฑฐ๋ ๋์์ undefined์ธ ๊ฒฝ์ฐ, ๋๊ฐ์ ์์ฑ์ ํ๋์ ๊ฐ์ฒด๋ก ๋ชจ์ผ๋ ๊ฒ์ด ๋ ์ข์ ์ค๊ณ์ด๋ค.
interface Person {
name: string;
// ๋ ๊ฐ์ด ๋์์ ์๊ฑฐ๋ ์์ด์ผ ํ๋ค
placeOfBirth?: string;
dateOfBirth?: Date;
}
interface Person {
name: string;
birth?: {
place: string;
date: Date;
}
}
API์ ๊ฒฐ๊ณผ์ ๊ฐ์ด ํ์ ์ ๊ตฌ์กฐ๋ฅผ ์ ๋ ์ ์๋ ์ํฉ์ด๋ฉด ์ธํฐํ์ด์ค์ ์ ๋์จ์ ์ฌ์ฉํด์ ์์ฑ ์ฌ์ด์ ๊ด๊ณ๋ฅผ ๋ชจ๋ธ๋งํ์.
string ํ์ ์ ๋ฒ์๋ ๋งค์ฐ ๋๋ค. ๋ณ์์ ๋ฒ์๋ฅผ ์ ํํ๊ฒ ํํํ๊ณ ์ ํ๋ค๋ฉด string ํ์ ๋ณด๋ค๋ ๋ฌธ์์ด ๋ฆฌํฐ๋ด์ ์ ๋์จ์ ์ฌ์ฉํ๋ฉด ๋๋ค.
function pluc(records: any[], key: string): any[] {
return records.map(r => r[key]);
}
// any๊ฐ ์์ด ์ข์ง ์๋ค. generic์ ๋์
ํด๋ณด์
function pluc2<T>(records: T[], key: string): any[] {
return records.map(r => r[key]);
// Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'unknown'.
// No index signature with a parameter of type 'string' was found on type 'unknown'.
}
// key์ ํ์
์ด string์ด๋ผ ๋ฒ์๊ฐ ๋๋ฌด ๋๋ค
// ๊ฐ์ฒด์ ์์ฑ ์ด๋ฆ์ ํจ์ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์ ๋๋ keyof T๋ฅผ ์ฌ์ฉํ์
function pluc3<T>( records: T[], key: keyof T){
return records.map(r => r[key]);
}
// ๋ฒ์๋ฅผ ๋ ์ขํ๊ธฐ ์ํด์ keyof T์ ๋ถ๋ถ์งํฉ์ ๋์
ํ์
// string ๋์ keyof๋ฅผ ์ฌ์ฉํ๋ฉด ์๋์์ฑ ๊ธฐ๋ฅ๋ ๊ฐ์ ๋๋ค
function pluc4<T, K extends keyof T>( records: T[], key: K): T[K][]{
return records.map(r => r[key]);
}
์ด๋ฆ์ผ๋ก ํ์ ์ ๊ตฌ๋ถํ๋ ๊ฒ. C, C++์์ ์ฌ์ฉํ๋ ๋ฐฉ์
class A {
method(input: string): number {...}
}
class B {
method(input: string): number {...}
}
let a: A = new B(); // Error
ํ์ ์คํฌ๋ฆฝํธ๋ ๊ธฐ๋ณธ์ ์ผ๋ก Structural ํ์ ์ธ๋ฐ ์ฝ๋๋ฅผ ๋ํ์ฌ normial์ ์ด์ ์ ๊ฐ์ ธ๊ฐ ์ ์๋ค. _brand( _brand ํ์์ ์ปจ๋ฒค์ ์ด๋ค)๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ด๋ค. ๊ฐ์ ๊ตฌ๋ถํ๊ธฐ ์ํด ์ํ๋ฅผ ๋ถ์ด๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ๋ฉด ์ข๋ค.
type ValidatedInputString = string & { __brand: "User Input Post Validation"}; // stringํ์
์ ์ํ ๋ถ์ด๊ธฐ
// ์ ์ฝ ์กฐ๊ฑด์ ๋ง์กฑํ๋ ๋ฌธ์์ด๋ก ๋ณํํ๋ ํจ์
const validateUserInput = (input: string) => {
const simpleValidatedInput = input.replace(/\</g, "<=");
return simpleValidatedInput as ValidatedInputString;
};
// ์กฐ๊ฑด์ ๋ง์กฑํ๋ ๋ฌธ์์ด๋ง ๋ฐ์ ์ถ๋ ฅํ๋ ํจ์
const printName = (name: ValidatedInputString) => {
console.log(name);
}
type Meters = number & {_brand: 'meters'} // numberํ์
์ ์ํ ๋ถ์ด๊ธฐ
// brand๋ฅผ ๋ถ์ฌ๋ ์ฐ์ ์ฐ์ฐ ํ์๋ ์์ด์ง๊ธฐ ๋๋ฌธ์ ์ฌ์ฉํ๊ธฐ์ ๋ฌธ๋ฆฌ๊ฐ ์์ ์ ์๋ค
๋๋์ด 3์ฅ ํ์ถ๐
type Language = 'Javascript' | 'Typescript' | 'Python';
function setLanguage(language: Language){ }
setLanguage('Javascript') // ์ ์
let language = 'Javascript';
setLanguage(language); // string ํ์์ ์ธ์๋ 'Language'ํ์์ ๋งค๊ฐ๋ณ์์ ํ ๋น ํ ์ ์์
๊ฐ์ ๋ณ์๋ก ๋ถ๋ฆฌํด๋ด๋ฉด์, ํ์ ์ string์ผ๋ก ์ถ๋ก ํ๊ณ Language ํ์ ์ ํ ๋น ๋ถ๊ฐ๋ฅํ๋ฏ๋ก ์๋ฌ๊ฐ ๋ฐ์ํ๊ฒ ๋๋ค
ํด๊ฒฐ ๋ฐฉ๋ฒ
ํ์ ์ ์ธ์์ language์ ๊ฐ๋ฅํ ๊ฐ์ ์ ํํ๋ ๊ฒ
let language: Language = 'Javascript';
language๋ฅผ ์์๋ก ๋ง๋๋ ๊ฒ
const language = 'Javascript';
setLanguage(language);
ํํ ์ฌ์ฉ ์ ์ฃผ์์
function panTo(where: [number, number]){}
panTo([10,20]); // ์ ์
const loc = [10,20];
panTo(loc) // ์๋ฌ ๋ฐ์! number[] ํ์์ [number,number]์ ํ ๋น ํ ์ ์๋ค
ํด๊ฒฐ ๋ฐฉ๋ฒ
ํ์ ์ ์ธ์ ์ ๊ณตํ๋ ๋ฐฉ๋ฒ
const loc : [number, number] = [10,20];
panTo(loc); // ์ ์
์์ ๋ฌธ๋งฅ์ ์ ๊ณตํ๊ธฐ , panTo ํจ์์ readonly ๊ตฌ๋ฌธ์ ์ถ๊ฐํ๋ ๊ฒ
const loc = [10, 20] as const;
panTo(loc); // readonly [10,20]์ ํ์์ readonly์ด๋ฉฐ
// ๋ณ๊ฒฝ๊ฐ๋ฅํ [number,number]์ ํ ๋น ํ ์ ์๋ค
fucntion panTo(where: readonly[number,number]) { }
const loc = [10, 20] as const;
panTo(loc); // ์ ์
as const์ ๋จ์
๊ฐ์ฒด ์ฌ์ฉ์ ์ฃผ์์
type Language = 'JavaScript' | 'TypeScript' | 'Python';
interface GovernedLanguage {
language : Language;
organization : string;
}
function complain(language: GovernedLanguage) { }
const ts = {
language: 'TypeScirpt',
organizaiton: 'Microsoft',
}
complain(ts) // language๊ฐ stringํ์
์ผ๋ก ์ถ๋ก ๋์ด์, ์๋ฌ๊ฐ ๋ฐ์ํ๊ฒ ๋๋ค
์ฝ๋ฐฑ ์ฌ์ฉ์ ์ฃผ์์
interface State {
pageText: string;
isLoading: boolean;
error ?: string;
}
function renderPage(state: State){
if(state.error){
return `Error`
} else if (state.isLoading){
return 'Loading';
}
return `ใดใดใดใด`
} -> isLoading์ด true์ด๊ณ error๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ์ ๋ํด์ ๋ก๋ฉ ์ค์ธ ์ํ์ธ์ง ์๋ฌ ์ํ์ธ์ง ๋ช
ํํ๊ฒ
๊ตฌ๋ถ์ด ๋ถ๊ฐ๋ฅํ๋ค
async function changePage(state: State, newPage: string){
state.isLoading = true;
try {
const response = await fetch(getUrlForPage(newPage));
if(!response.ok){
throw new Error(`unable to load`); -> ์ค๋ฅ๊ฐ ๋ฐ์ํ์ ๋์, isLoading์ด false๋ก
๋๋ ๋ก์ง ๋ถ์ฌ
-> state.error๋ฅผ ์ด๊ธฐํํ์ง ์์ ๊ณผ๊ฑฐ์ ์ค๋ฅ ๋ฉ์ธ์ง๊ฐ ๋ณด์ฌ์ง ์ ์๋ค
}
const text = await response.text();
state.isLoading = false;
state.pageText = text;
} catch (e) {
state.error = ' ' | e;
}
}
-> ํ์ด์ง ๋ก๋ฉ ์ค์ ์ฌ์ฉ์์ ํ์ด์ง๊ฐ ๋ฐ๋์ด ๋ฒ๋ฆฌ๋ฉด, ์ด๋ค ์ผ์ด ๋ฐ์ํ ์ง ์์ํ๊ธฐ ์ด๋ ต๋ค.
interface RequestPending {
state: 'pending';
}
interface RequestError {
state: 'error';
error: string;
}
interface RequestSuccess {
state: 'ok';
pageText: string;
}
type RequestState = RequestPending | RequestError | RequestSuccess;
interface Vector2D{
x: number;
y: number;
}
function calculateNorm(p:Vector2D){}
const vec3D = {x: 3, y:4, z:1};
calculateNorm(vec3D); // ์ ์!!
interface Vector2D{
_brand:'2D';
x: number;
y: number;
}
function calculateNorm(p:Vector2D){}
const vec3D = {x: 3, y:4, z:1};
calculateNorm(vec3D); // _brand ์์ฑ์ด ํ์์ ์์ต๋๋ค.
type AbsoultePath = string & {_brand:'abs'};
function listAbsolutePath(path: AbsoultePath){
// ..
}
function isAbsolutePath(path:string): path is AbsoultePath{
return path.startsWith('/');
}
function f(path:string){
if(isAbsolutePath(path)){
listAbsolutePath(path);
}
listAbsolutePath(path); // error
}
type Bar = 'example';
function processBar(b:Bar){}
function f1(){
const x: any = 'foo';
processBar(x); // ์ด๋ ๊ฒ ํ์ง๋ง์์ค
}
function f2(){
const x= 'foo';
processBar(x as any); // ์ด๊ฒ ๋ซ๋ค.
}
์นจ์ฐฉํด. ๋ค๊ฐ ๊ฐ์ผํ ๊ณณ์๋ง ์ง์คํด์ผ ํด. ๐๐๐
strickNullChecks
๋ฅผ ์ค์ ํ๋ฉด null ๊ฐ๊ณผ ๊ด๋ จ๋ ๋ฌธ์ ์ ์ ์ฐพ์ ์ ์์ผ๋ฏ๋ก ๋ฐ๋์ ํ์ํ๋ค.์ ๋์จ ํ์ ์ ์์ฑ์ ๊ฐ์ง๋ ์ธํฐํ์ด์ค๋ฅผ ์์ฑ ์ค์ด๋ผ๋ฉด, ์ธํฐํ์ด์ค์ ์ ๋์จ ํ์ ์ ์ฌ์ฉํ๋ ๊ฒ ๋ ์ ์ ํ์ง ์์์ง ๊ฒํ ํด๋ณธ๋ค. ์ ๋์จ ํ์ ์ ์์ฑ์ ์ฌ๋ฌ ๊ฐ ๊ฐ์ง๋ ๊ฒฝ์ฐ, ์์ฑ ๊ฐ์ ๊ด๊ณ๊ฐ ๋ถ๋ช ํ์ง ์์ ์ค์๊ฐ ์์ฃผ ๋ฐ์ํ๋ค. ์ธํฐํ์ด์ค์ ์ ๋์จ์ผ๋ก ํํํ๋ ๋ฐฉ์์ด ๋ ์ ํํ๊ณ ํ์ ์คํฌ๋ฆฝํธ๊ฐ ์ดํดํ๊ธฐ ์ข๋ค.
ํ๊ทธ๋ ์ ๋์จ์ ํ์ ์คํฌ๋ฆฝํธ์ ์ ๋ง๋ค. ์ด๋ค ๋ฐ์ดํฐ ํ์ ์ ํ๊ทธ๋ ์ ๋์จ์ผ๋ก ํํํ ์ ์๋ค๋ฉด ๋ณดํต์ ๊ทธ๋ ๊ฒ ํ๋ ๊ฒ์ด ์ข๋ค. ์ฌ๋ฌ ๊ฐ์ ์ ํ์ ํ๋๊ฐ ๋์์ ๊ฐ์ด ์๊ฑฐ๋ ์๋(undefined)์ธ ๊ฒฝ์ฐ๋ ํ๊ทธ๋ ์ ๋์จ ํจํด์ด ์ ๋ง๋ค.
interface Layer {
layout: FillLayout | LineLayout | PointLayout;
paint: FillPaint | LinePaint | PointPaint;
}
// ์ ์ธํฐํ์ด์ค๋ LineLayout๊ณผ FillPaint์ ๊ฐ์ ์กฐํฉ์ ํ์ฉํ๋ค.
// ์ด์ ๊ฐ์ ์กฐํฉ์ ํ์ฉํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฌ์ฐ๋ฏ๋ก ์ธํฐํ์ด์ค๋ฅผ ๋ถ๋ฆฌํ๋ค.
// type ์์ฑ์ 'ํ๊ทธ'๋ก ์ถ๊ฐํ์ฌ ๋ฐํ์์ ์ด๋ค ํ์
์ด ์ฌ์ฉ๋๋์ง ํ๋จํ๋๋ฐ ์ฌ์ฉํ์.
// ํ์
์คํฌ๋ฆฝํธ๋ ํ๊ทธ๋ฅผ ์ฐธ๊ณ ํ์ฌ ํ์
์ ๋ฒ์๋ฅผ ์ขํ๋ค.
interface FillLayer {
type: 'fill';
layout: FillLayout;
paint: FillPaint;
}
interface LineLayer {
type: 'line';
layout: LineLayout;
paint: LinePaint;
}
interface PointLayer {
type: 'paint';
layout: PointLayout;
paint: PointPaint;
}
type Layer = FillLayer | LineLayer | PointLayer;
๋ ์์ฑ์ด ๋์์ ์๊ฑฐ๋ ์๋ ๊ฒฝ์ฐ ๋ ๊ฐ์ ์์ฑ์ ํ๋์ ๊ฐ์ฒด๋ก ๋ชจ์ผ๋ ์ค๊ณ๊ฐ ๋ ๋ซ๋ค.
interface Person {
name: string;
placeOfBirth?: string;
dateOfBirth?: Date;
}
// placeOfBirth์ dateOfBirth๋ ํจ๊ป ์๊ฑฐ๋ ํจ๊ป ์๋ค.
// ๋ ํ๋๋ ์๋ก ๊ด๋ จ๋์ด ์์ง๋ง ํ์
์ ๋ณด์์๋ ๊ด๋ จ์ฑ์ด ๋๋ฌ๋์ง ์๋๋ค.
// ๋ ์์ฑ์ ํ๋์ ๊ฐ์ฒด๋ก ๋ชจ์ ํ์
์ ๋ณด์ ๊ด๊ณ๋ฅผ ํํํ๋ค.
interface Person {
name: string;
birth?: {
place: string;
date: Date;
}
}
// ์์ ๊ฐ์ด ์์ฑํ๋ฉด
// 1. place ์์ด date๋ง ์๋ ๊ฒฝ์ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
// 2. Person ํ์
์ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ ๋ birth์ ์กด์ฌ ์ฌ๋ถ๋ง ์ฒดํฌํ๋ฉด ๋๋ค.
API ์๋ต ๊ฒฐ๊ณผ์ ๊ฒฝ์ฐ ํ์ ์ ๊ตฌ์กฐ์ ์ ๋ ์ ์๋ค. ์ด ๊ฒฝ์ฐ ์ธํฐํ์ด์ค์ ์ ๋์จ์ ์ฌ์ฉํ์ฌ ์์ฑ ์ฌ์ด์ ๊ด๊ณ๋ฅผ ๋ชจ๋ธ๋งํ ์ ์๋ค.
interface Name {
name: string;
}
interface PersonWithBirth extends Name {
placeOfBirth: string;
dateOfBirth: Date;
}
type Person = Name | PersonWithBirth;
function eulogize(p: Person) {
if ('placeOfBirth' in p) {
// ํ์
์ด PersonWithBirth
}
}
string ํ์ ๋ณด๋ค ๋ ๊ตฌ์ฒด์ ์ธ ํ์ ์ ์ฌ์ฉํ๋ฉด ํ์ ์คํฌ๋ฆฝํธ๋ ์ค๋ฅ๋ฅผ ๋ ์ ์ฒดํฌํ ์ ์๋ค.
๊ตฌ์ฒด์ ์ธ ํ์ ์ฌ์ฉ์ ์์
keyof T
๋ฅผ ์ฌ์ฉtype RecordingType = 'studio' | 'live';
interface Album {
artist: string;
title: string;
releaseDate: Date;
recordingType: RecordingType;
}
๊ตฌ์ฒด์ ์ธ ํ์ ์ฌ์ฉ์ ์ฅ์
keyof
์ฐ์ฐ์๋ก ๋์ฑ ์ธ๋ฐํ ๊ฐ์ฒด ์์ฑ ์ฒดํฌ๊ฐ ๊ฐ๋ฅํด์ง๋ค.
keyof
์ ๋งค๊ฐ๋ณ์ ํ์
์ ์ฌ์ฉํ๋ฉด ํธ์ง๊ธฐ์ ์๋ ์์ฑ ๊ธฐ๋ฅ๋ ๊ฐ์ ๋๋ค.
// ๋ฐฐ์ด ์์์์ ํ ํ๋์ ๊ฐ์ ์ถ์ถํ๋ ํจ์๋ฅผ ์์ฑํด๋ณด์.
function pluck<T>(records: T[], key: keyof T) {
return records.map(record => record[key]);
}
// ํจ์์ ํ์
์ function pluck<T>(records: T[], key: keyof T): T[keyof T][]
const albums: Album[] = [];
const releaseDates = pluck(albums, 'releaseDate');
// releaseDates์ ํ์
์ (string | Date)[]
// T[keyof T][]์ ๋ฒ์๋ ๋๋ค. ๋ฒ์๋ฅผ ์ขํ์ฃผ์!
// ๋ ๋ฒ์งธ ์ ๋๋ฆญ ๋งค๊ฐ๋ณ์๋ก keyof T์ ๋ถ๋ถ ์งํฉ์ธ K๋ฅผ ๋์
ํ๋ค.
function pluck<T, K extends keyof T>(records: T[], key: K): T[K][] {
return records.map(record => record[key]);
}
any์ unknown์ ๊ตฌ๋ณํด์ ์ฌ์ฉํ๋ค. any๋ ํ์ ์ ์ขํ์ง ์์๋ ๋์ง๋ง, unknown์ ํ์ ์ ๋จผ์ ํ์ธํ ํ์ ์ฌ์ฉํ ์ ์์ด any๋ณด๋ค ์์ ํ๋ค.
์์ ๋ฐ์ดํฐ๋ฅผ ์ฐธ๊ณ ํด ํ์ ์ ์์ฑํ๋ฉด ๋ณด์ด๋ ๋ฐ์ดํฐ๋ง ๊ณ ๋ คํ๊ฒ ๋๋ฏ๋ก ์๊ธฐ์น ์์ ๊ณณ์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ์๋ค. ๋ช ์ธ๋ฅผ ์ฐธ๊ณ ํด ํ์ ์ ์์ฑํ๋ ๊ฒ์ด ์ข๋ค.
ํ์ ์คํฌ๋ฆฝํธ๋ structural typing์ด๋ผ, ๊ฐ์ ์ธ๋ฐํ๊ฒ ๊ตฌ๋ถํ์ง ๋ชปํ๋ ๊ฒฝ์ฐ๊ฐ ์๋ค. ๊ฐ์ ์ธ๋ฐํ๊ฒ ๊ตฌ๋ถํ๋ ค๋ฉด nominal typing์ด ํ์ํ๋ค. Nominal typing์ ํ์ ์คํฌ๋ฆฝํธ์์ ํ๋ด ๋ด๋ ค๋ฉด, ์ํ(_brand)๋ฅผ ๋ถ์ด๋ฉด ๋๋ค.
interface Vector2D {
_brand: '2d';
x: number;
y: number;
}
function vec2D(x: number, y: number): Vector2D {
return {x, y, _brand: '2d'};
}
function calculateNorm(p: Vector2D) {
return Math.sqrt(p.x * p.x + p.y * p.y);
}
calculateNorm(vec2D(3, 4)); // ์ ์, 5 ๋ฐํ
const vec3D = {x: 3, y: 4, z: 1};
calculateNorm(vec3D); // ์ค๋ฅ! '_brand' ์์ฑ์ด ... ํ์์ ์์ต๋๋ค.
์ํ ๊ธฐ๋ฒ์ ํ์ ์์คํ ์์ ๋์ํ์ง๋ฉด ๋ฐํ์์ ๊ฒ์ฌํ๋ ๊ฒ๊ณผ ๋์ผํ ํจ๊ณผ๋ฅผ ์ป์ ์ ์๋ค. ํ์ ์์คํ ์ด๊ธฐ ๋๋ฌธ์ ๋ฐํ์ ์ค๋ฒํค๋๋ฅผ ์์จ ์ ์๊ณ , ์ถ๊ฐ ์์ฑ์ ๋ถ์ผ ์ ์๋ ๋ด์ฅ ํ์ (string์ด๋ number ๊ฐ์)๋ ์ํํํ ์ ์๋ค.
type AbsolutePath = string & { _brand: 'abs' };
// string ํ์
์ด๋ฉด์ _brand ์์ฑ์ ๊ฐ์ง๋ ๊ฐ์ฒด๋ฅผ ๋ง๋ค ์๋ ์๋ค.
// ์ด๋ ํ์
์์คํ
์ด๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฅํ๋ค!
function listAbsolutePath(path: AbsolutePath) { /* */ };
function isAbolustePath(path: string): path is AbsolutePath {
return path.startsWith('/');
}
function f(path: string) {
if (isAbolustePath(path)) {
// path์ ํ์
์ AbsolutePath
listAbsolutePath(path);
}
// path์ ํ์
์ string
listAbsolutePath(path);
// ์ค๋ฅ! string ํ์์ AbsolutePath ํ์์ ๋งค๊ฐ๋ณ์์ ํ ๋น๋ ์ ์๋ค.
}
// number ํ์
์๋ ์ํ๋ฅผ ๋ถ์ผ ์ ์๋ค.
type Meters = number & { _brand: 'meters' };
const meters = (m: number) => m as Meters;
const oneKm = meters(1000); // ํ์
Meters
const tenKm = 10 * oneKm; // ํ์
number
// ๋จ, ์ฐ์ ์ฐ์ฐ ํ์๋ ์ํ๊ฐ ์์ด์ง๋ค.
์์ฐจ ์์ฐจ ๐