2024-06-06.md
๐กDIL: ์ดํํฐ๋ธ ํ์ ์คํฌ๋ฆฝํธ
์คํฐ๋: ์๊ฐ CS, https://github.com/monthly-cs/2024-05-effective-typescript
์์ฑ์ผ: 2024-06-06
์์ฑ์: dusunax
์์ดํ 42: ๋ชจ๋ฅด๋ ํ์ ์ ๊ฐ์๋ any ๋์ unknown์ ์ฌ์ฉํ๊ธฐ Use unknown Instead of any for Values with an Unknown Type
unknown
- ํจ์์ ๋ฐํ๊ฐ๊ณผ ๊ด๋ จ๋ ํํ
- ๋ณ์ ์ ์ธ๊ณผ ๊ด๋ จ๋ ํํ
- ๋จ์ธ๋ฌธ๊ณผ ๊ด๋ จ๋ ํํ
์์: parseYAML ํจ์
function parseYAML(yaml: string): any {}
interface Book {
name: string;
author: string;
}
const book: Book = parseYAML(` // ๋ฐํ๊ฐ์ ์ํ๋ ํ์
์ผ๋ก ํ ๋นํด์ ์ฌ์ฉ
name: Wuthering Heights
author: Emily Brontรซ
`); // any => Book
// ํธ์ถํ ๊ณณ์์ ํ์
์ ์ธ์ ์๋ตํ๊ฒ ๋๋ฉด? book ๋ณ์๋ ์์์ ์ธ any ํ์
์ด ๋๋ค.
// ๋ฐํ์ ์ค๋ฅ ๋ฐ์!!
const book = parseYAML(`
name: Jane Eyre
author: Charlotte Brontรซ
`); // any
console.log(book.title); // No error, logs "undefined" at runtime
book("read"); // No error, throws "book is not a function" at runtime
// unknown์ returnํ๋ ๊ฒ์ด ์์ ํ๋ค๐
// unknown ๊ทธ๋๋ก ๊ฐ์ ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์, Book์ผ๋ก ํ์
๋จ์ธ์ ํด์ผ ํ๋ค.
// ๋จ์ธ? ์ ์ด์ Book ํ์
์ ๊ธฐ๋ํ๊ณ ํจ์๋ฅผ ํธ์ถํจ
function safeParseYAML(yaml: string): unknown {
return parseYAML(yaml);
}
const book = safeParseYAML(`
name: The Tenant of Wildfell Hall
author: Anne Brontรซ
`);
console.log(book.title);
// ~~~~ 'book' is of type 'unknown'
book("read");
// Error: 'book' is of type 'unknown'
- ๋ถ๋ถ ์งํฉ์ด๋ฉด์ ์์ ์งํฉ์ด ๋๊ธฐ ๋๋ฌธ์ any๋ ํ์
์์คํ
๊ณผ ์์ถฉ๋๋ ๋ฉด์ด ์๋ค.
- ํ์ ์ฒด์ปค๋ ์งํฉ ๊ธฐ๋ฐ์ด๊ธฐ ๋๋ฌธ์ ๋ฌด์ฉ์ง๋ฌผ์ด ๋๋ค.
any & unknown & never
| ํน์ง / ํ์
| ์ด๋ค ํ์
์ด๋ ํ ๋น ๊ฐ๋ฅ | ์ด๋ ํ ํ์
์ผ๋ก๋ ํ ๋น๋จ |
| ----------- | ----------------------- | ----------------------------------- |
| any
| O | O (์์ธ: never
์๋ง ํ ๋น ๋ถ๊ฐ) |
| unknown
| O | X (unknown
๊ณผ any
์๋ง ํ ๋น ๊ฐ๋ฅ) |
| never
| X | O |
let valueAny: any;
let valueUnknown: unknown;
let valueNever: never;
// ์ด๋ค ํ์
์ด๋ ํ ๋น ๊ฐ๋ฅ
// โญ๏ธ any
valueAny = 123; // O
valueAny = "string"; // O
valueAny = true; // O
// โญ๏ธ unknown
valueUnknown = 123; // O
valueUnknown = "string"; // O
valueUnknown = true; // O
// โ never
valueNever = 123; // X
valueNever = "string"; // X
valueNever = true; // X
// ์ด๋ ํ ํ์
์๋ ํ ๋น๋จ
let num: number;
num = valueAny; // O (์์ธ: `never`์๋ง ํ ๋น ๋ถ๊ฐ) // num์ ํ์
์ number
num = valueUnknown; // X (number์ unknown์ ํ ๋นํ ์ ์๋ค.) // num์ ํ์
์ number
num = valueNever; // O (์์ธ ์์) // num์ ํ์
์ number
- ์ด๋ค ํ์ ์๋ never๊ฐ ๋ค์ด๊ฐ ์ ์๋ค๋ ๊ฒ์ด ์ ๊ธฐํ๋ค. (์งํฉ ๊ด์ )
์์: ๋ณ์ ์ ์ธ
- ์ด๋ ํ ๊ฐ์ ํ์ ์ ๋ชจ๋ฅด๋ ๊ฒฝ์ฐ, unknown์ ์ฌ์ฉํ๋ค.
// ๋ญ๋ ๋ค์ด๊ฐ. grab-bag
interface Feature {
id?: string | number;
geometry: Geometry;
properties: unknown;
}
// ๋ฐฐ์ด ์์์ ํ์
์ ๋ชจ๋ฅด๋ ๊ฒฝ์ฐ
function isSmallArray(arr: readonly unknown[]): boolean {
return arr.length < 10;
}
// ์ด๋ค ๊ฐ์ด ๋ค์ด์ฌ ์ง ๋ชจ๋ฅด๋ ๊ฒฝ์ฐ
function processValue(value: unknown) {
if (value instanceof Date) {
value;
// ^? (parameter) value: Date
}
}
// ์ฌ์ฉ์ ์ ์ ํ์
๊ฐ๋: unknown ์ขํ๊ธฐ์ฉ
function isBook(value: unknown): value is Book {
return (
typeof value === "object" &&
value !== null &&
"name" in value &&
"author" in value
);
}
function processValue(value: unknown) {
if (isBook(value)) {
// ์ฌ์ฉ์ ์ ์ ํ์
๊ฐ๋!
value;
// ^? (parameter) value: Book
}
}
// ์ ๋๋ฆญ์ ์๋ชป ์ฌ์ฉํ์ง ๋ง๊ณ , unknown์ ๋ฐํํ์.
// ์๋ ์ฝ๋์ ์ ๋๋ฆญ์ ํ์
๋จ์ธ์ด๋ ๋ง์ฐฌ๊ฐ์ง์ ๊ธฐ๋ฅ์ด๋ค.
function safeParseYAML<T>(yaml: string): T {
return parseYAML(yaml);
}
ํ์ ์บ์คํ / ๋จ์ธ๋ฌธ ์ฌ์ฉ ์
- ๊ธฐ๋ฅ์ ์ผ๋ก ๋์ผํ๋ค.
- ๋ค๋ง ๋์ค์ ๋จ์ธ๋ฌธ์ ๋ถ๋ฆฌํ๋ ๋ฆฌํฉํฐ๋ง ๋ฑ์ ๊ณ ๋ คํ์ฌ unknown ์ฌ์ฉํ๊ธฐ
declare const foo: Foo;
let barAny = foo as any as Bar; // โ
let barUnk = foo as unknown as Bar; // โญ๏ธ
unknown๊ณผ ์ ์ฌํ ํ์ : object ๋๋ {}
- ๋ฒ์๊ฐ ๋์ง๋ง, unknown๋ณด๋ค๋ ์ข๋ค.
- {}๋ null๊ณผ undefined๋ฅผ ์ ์ธํ ๋ชจ๋ ๊ฐ์ ํฌํจํ๋ค. (๋น ๊ฐ์ฒด๊ฐ ์๋. ํ์ ์)
- object๋ ๋ชจ๋ ๋น๊ธฐ๋ณธํ(non-primitive) ํ์
- ๊ฐ์ฒด, ๋ฐฐ์ด ํฌํจ
type ABC = {};
const abc: ABC = "abc";
type DEF = object;
const def: DEF = ["def"];
- unknown ํ์ ๋์ ์ ์๋ {}๊ฐ ์ผ๋ฐ์ ์ผ๋ก ์ฐ์๋ค. ์ต๊ทผ์๋ unknown์ ์ฃผ๋ก ์ฌ์ฉํ๊ณ , ์ ๋ง null๊ณผ undefined๊ฐ ์๋ ๋๋ง {}๋ฅผ ์ฌ์ฉํ ์ ์์
Things to Remember
- The unknown type is a type-safe alternative to any. Use it when you know you have a value but do not know or do not care what its type is.
- unknown์ any ๋์ ์ฌ์ฉํ ์ ์๋, ์์ ํ ํ์ ์ด๋ค. ์ด๋ค ๊ฐ์ ํ์ ์ ์์ง๋ชปํ๋ฉด unknown์ ์ฌ์ฉํ๋ค.
- Use unknown to force your users to use a type assertion or other form of narrowing.
- unknown์ ์ฌ์ฉํด์ ์ฌ์ฉ์๊ฐ ํ์ ๋จ์ธ๋ฌธ์ด๋ ํ์ ์ฒดํฌ๋ฅผ ์ฌ์ฉํ๋๋ก ๊ฐ์ ํ ์ ์๋ค.
- Avoid return-only type parameters, which can create a false sense of security.
- ํ์ ๋จ์ธ์ด๋ ๋ง์ฐฌ๊ฐ์ง์ธ ์ ๋๋ฆญ ์ฌ์ฉ ์กฐ์ฌ (์์ ํ ํ์ ์ด๋ผ๊ณ ์ฐฉ๊ฐํ ์ ์๋ค.)
- Understand the difference between {}, object, and unknown.
- {}, object, unknown ํ์ ์ ์ฐจ์ด์ ์๊ธฐ