[TS] ํ์ ์คํฌ๋ฆฝํธ ํ์ ๊ฐ๋ is / asserts ํค์๋ ์ฐจ์ด์
TL;DR
- parameterName is Type : ์กฐ๊ฑด๋ฌธ์์ ์ฌ์ฉ (
if
๋ฌธ์ผ๋ก ํ์ ์ ๋ถ๊ธฐ ์ฒ๋ฆฌํ ๋ ์ฌ์ฉ) - asserts parameterName is Type : ์์ธ๋ฅผ ๋ฐ์์ํด (์ค์ฝํ ๋ด์์ ์ ํจํ ํ์ ์ธ์ง ํ๋จํ ๋ ์ฌ์ฉ)
is ํค์๋
ํ์
์คํฌ๋ฆฝํธ์์ ํ์
๋ฒ์๋ฅผ ์ขํ๋๊ฐ๋ ์์
(๊ธฐ๋ฅ)์ ํ์
๊ฐ๋๋ผ๊ณ ๋ถ๋ฅธ๋ค. ๊ฐ๋จํ ํ์
์ in
, typeof
ํค์๋ ๋ฑ์ ์ฌ์ฉํ ์ ์์ง๋ง โํ์
์ด ๋ณต์กํ๊ฑฐ๋ โํ์
์ฒดํฌ ๋ก์ง์ ์ฌ์ฌ์ฉํ๊ณ ์ถ์ ๋ ์ฌ์ฉ์ ์ ์ ํ์
๊ฐ๋ ํจ์๋ฅผ ๋ง๋ค์ด์ ์ฌ์ฉํ๋ค. ํ์
๊ฐ๋ ํจ์๋ ๋ฆฌํด๋ฌธ์ is
ํค์๋๋ฅผ ์ด์ฉํด์ “์ด๋ค ์ธ์๋ ์ด๋ค ํ์
์ด๋ค” ๋ผ๋ ๊ฐ(ํ์
๋ช
์ /์ ๋ถ; Predicate)์ ๋ฆฌํดํ๋ ํจ์๋ผ๊ณ ๋ณผ ์ ์๋ค.
๐ก ์ ๋ถ(Predicate; ่ฐ่ฏ)๋? ์ฃผ์ด์ ์ํ, ์ฑ์ง ๋ฐ์๋ฅผ ์์ ํ๋ ๋ง(์ฐธ๊ณ ). value is Type
ํํ๋ ์ ๋ถ๋ณด๋จ ๋ช
์ (๊ณ ๋๋ ํฌ์ ๋ฅ๋ค ์ฒ๋ผ ์ฐธ/๊ฑฐ์ง์ ํ๋จํ ์ ์๋ ๋ด์ฉ)๊ฐ ๋ ์ด์ธ๋ฆฌ๋ ๋จ์ด์ธ ๊ฒ ๊ฐ๋ค.
์๋ logPersonAge
ํจ์๋ Person
, Product
๋๊ฐ์ง ํ์
์ ์ธ์๋ฅผ ๋ฐ๋๋ค. ํ์
์คํฌ๋ฆฝํธ๋ ์ด๋ค ํ์
์ ๊ฐ์ ์ธ์๋ก ๋ฐ์์ง ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ ํ์
๊ฐ๋ ์์ด value.age
๊ฐ์ ์ฌ์ฉํ๋ฉด ts(2339) ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
interface Person {
name: string;
age: number;
}
interface Product {
name: string;
price: number;
}
// ํ์
๊ฐ๋ ํจ์๋ ์ฃผ๋ก isTypeName ํํ์ ํจ์๋ช
์ ์ฌ์ฉํ๋ค
// is ํค์๋๋ parameterName is Type ํํ๋ก ์ฌ์ฉํ๋ค
function isPerson(value: Person | Product): value is Person {
return (value as Person).age !== undefined; // true | false
}
function logPersonAge(value: Person | Product) {
console.log(value.age); // Error! Property 'age' does not exist on type 'Product'
if (isPerson(value)) console.log(value.age);
else console.log('value does not have age properties');
}
logPersonAge({ name: 'smith', age: 30 }); // 30
logPersonAge({ name: 'iPhone', price: 600 }); // value does not have age properties
๐ก isPerson
ํจ์ ๋ฆฌํด ํ์
์ ๋ช
์ํ value is Person
๊ตฌ๋ฌธ์ด ํ์
๋ช
์ (์ ๋ถ)๋ค.
์ด์ฒ๋ผ is
ํค์๋๋ฅผ ์ฌ์ฉํด์ boolean ๊ฐ์ ๋ฐํํ๋ ํจ์๋ฅผ type predicates(ํ์
๋ช
์ )๋ผ๊ณ ๋ถ๋ฅธ๋ค. ์ฆ, ๋ฐํ ํ์
์ด ํ์
๋ช
์ ์ธ ํจ์๋ ์์ธ๋ฅผ ๋ฐ์์ํค์ง ์๊ณ ๋จ์ํ boolean ๊ฐ์ ๋ฐํํ๋ค. ๋ฐํํ boolean ๊ฐ์ด ์ฐธ์ด๋ผ๋ฉด ํจ์๋ฅผ ํธ์ถํ ์ค์ฝํ๋ด์์ ํด๋น ๋ช
์ (value is Type
)์ ํ์
์ ๋ณด๊ฐ ์ ์ฉ๋๋ค.
์๋๋ ์
๋ ฅ๋ฐ์ ํ๋ผ๋ฏธํฐ๊ฐ number
ํ์
์ธ์ง ํ์ธํ๋ isNumber
ํ์
๊ฐ๋ ์์. Array.at()
๋ฉ์๋๋ ์ธ์์ ๋ช
์ํ ์ธ๋ฑ์ค์ ์์๋ฅผ ๋ฐํํ๋๋ฐ, ์์๊ฐ ์กด์ฌํ์ง ์์ ์๋ ์๊ธฐ ๋๋ฌธ์ ์์ํ์
| undefined
์ ๋์จ ํ์
์ ๊ฐ๋๋ค. ์์ ํ์
์ ํ์ธํ ๋ lastEl !== undefined
๊ฐ์ ์กฐ๊ฑด๋ฌธ ๋์ isNumber
ํ์
๊ฐ๋๋ฅผ ์ ์ฉํ๋ฉด undefined
ํ์
๋ฟ๋ง ์๋๋ผ ์ค์ ๋ก number
ํ์
์ธ์ง๋ ํ์ธํ ์ ์๋ ์ฅ์ ์ด ์๋ค.
// ํ์
๊ฐ๋ ์ ์
const isNumber = (value: unknown): value is number => {
return typeof value === 'number' && !isNaN(value); // true or false ๋ฐํ
};
const arr = [1, 2, 3];
const lastEl = arr.at(-1); // number | undefined
// ํ์
๊ฐ๋๋ฅผ ์ฌ์ฉํ์ฌ number ํ์
์ธ์ง ํ์ธ
if (isNumber(lastEl)) {
console.log('Last element is a number:', lastEl);
} else {
console.log('Last element is not a number or is undefined');
}
asserts ํค์๋
asserts
, is
ํค์๋๋ฅผ ํจ๊ป ์ฌ์ฉํด์ ์ ์ฌ์ ์ธ ์์ธ๋ฅผ ๋ฐ์(throw
)์ํค๊ณ , void
๋ฅผ ๋ฆฌํดํ๋ ํจ์(๋ฆฌํด๊ฐ์ด ์๋ ํจ์)๋ assertion functions๋ผ๊ณ ๋ถ๋ฅธ๋ค. assertion ํจ์๊ฐ ์์ธ๋ฅผ ๋ฐ์์ํค์ง ์๋๋ค๋ฉด ๋ฆฌํด๊ฐ์ ๋ช
์ (value is Type
)๋ ์ฐธ์ด ๋๊ณ , ํจ์๋ฅผ ํธ์ถํ ์ค์ฝํ๋ด์์ ๋ช
์ ์ ํ์
์ ๋ณด๊ฐ ์ ์ฉ๋๋ค.
์ฝ๋ ์ถ์ฒ StackOverflow โผ
// predicate
function exists<T>(maybe: T): maybe is NonNullable<T> {
return maybe != null;
}
// assertion
function assertExists<T>(maybe: T): asserts maybe is NonNullable<T> {
if (maybe === null) throw new Error(`${maybe} doesn't exist`);
}
function example1() {
console.log('example1 begin');
let maybe: string | undefined;
if (exists(maybe)) {
maybe; // string
} else {
maybe; // undefined
}
console.log('example1 end');
}
function example2() {
console.log('example2 begin');
let maybe: string | undefined;
assertExists(maybe);
maybe; // string
console.log('example2 end');
}
example1(); // 'example1 begin' then 'example1 end'
example2(); // only 'example2 begin', then exception is thrown: `undefined doesn't exist`
// ์์ 1
function assertIsString(value: unknown): asserts value is string {
if (typeof value !== 'string') throw new Error('value is not string');
}
function printName(name: unknown) {
assertIsString(name);
console.log(name);
}
printName('smith'); // smith
printName({}); // Error: value is not string
// ์์ 2
interface User {
name: string;
displayName: string | null;
}
// user.displayName?.toUpperCase์ ์ต์
๋ ์ฒด์ด๋์ ์ฌ์ฉํ๊ธฐ ์ซ๋ค๋ฉด ํ์
๋ช
์ ๋ฅผ ์๋์ฒ๋ผ ์์
// asserts user is User & { displayName: string }
function assertDisplayName(user: User): asserts user is User {
if (!user.displayName) throw new Error('Oops! there is no displayName');
}
function logUserDisplayName(user: User) {
assertDisplayName(user);
console.log(user.displayName?.toUpperCase());
}
logUserDisplayName({ name: 'smith', displayName: '์ค๋ฏธ์ค ์์' }); // ์ค๋ฏธ์ค ์์
logUserDisplayName({ name: 'smith', displayName: null }); // Error: oops! there is no displayName
๋ ํผ๋ฐ์ค
- What is the difference between "asserts value is type" and "value is type" in TypeScript?
- Documentation - Narrowing
- ํ๋์ ๋ณด๋ ํ์ ์คํฌ๋ฆฝํธ(updated)
๊ธ ์์ ์ฌํญ์ ๋ ธ์ ํ์ด์ง์ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ๋ฐ์๋ฉ๋๋ค. ๋งํฌ๋ฅผ ์ฐธ๊ณ ํด ์ฃผ์ธ์
'๐ช Programming' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote
๋ค๋ฅธ ๊ธ
-
[JS] ํน์ ์์ ์์น๋ก ์คํฌ๋กค ์ด๋ํ๊ธฐ - scrollIntoView
[JS] ํน์ ์์ ์์น๋ก ์คํฌ๋กค ์ด๋ํ๊ธฐ - scrollIntoView
2024.05.11 -
[React] ๋ฆฌ์กํธ Render Props ํจํด 2๊ฐ์ง ์ฌ์ฉ ๋ฐฉ๋ฒ
[React] ๋ฆฌ์กํธ Render Props ํจํด 2๊ฐ์ง ์ฌ์ฉ ๋ฐฉ๋ฒ
2024.05.11 -
[DevTools] ๊ฐ๋ฐ์ ์นํ์ ์ธ ํฐ๋ฏธ๋ LS — PLS
[DevTools] ๊ฐ๋ฐ์ ์นํ์ ์ธ ํฐ๋ฏธ๋ LS — PLS
2024.05.10 -
[HTML/CSS] ํผ์นจ/์ ํ Transition ํจ๊ณผ์ ์์ ์จ๊น ๋ฐฉ์ ์ฐจ์ด์
[HTML/CSS] ํผ์นจ/์ ํ Transition ํจ๊ณผ์ ์์ ์จ๊น ๋ฐฉ์ ์ฐจ์ด์
2024.05.10