2024-05-21.md
π‘DIL: μ΄νν°λΈ νμ μ€ν¬λ¦½νΈ
μ€ν°λ: μκ° CS, https://github.com/monthly-cs/2024-05-effective-typescript
μμ±μΌ: 2024-05-21
μμ±μ: dusunax
νμ μ€ν¬λ¦½νΈ
μμ΄ν 19: μΆλ‘ κ°λ₯ νμ μ μ¬μ©ν΄ μ₯ν©ν μ½λ λ°©μ§νκΈ° Avoid Cluttering Your Code with Inferable Types
νμ μΆλ‘
- λͺ¨λ λ³μμ νμ μ μΈνλ κ²μ λΉμμ°μ / λΆνμ
// not good!
let x: number = 12;
// enough!
let x = 12;
- νμ μΆλ‘ μ΄ λλ€λ©΄ λͺ μμ νμ ꡬ문μ νμνμ§ μμ (μ€νλ € λ°©ν΄)
- 볡μ‘ν κ°μ²΄ λλ ν¨μμ λ°ν νμ λ μΆλ‘ ν μ μμ
// κ°μ²΄ μΆλ‘
const person = {
name: "Sojourner Truth",
born: {
where: "Swartekill, NY",
when: "c.1797",
},
died: {
where: "Battle Creek, MI",
when: "Nov. 26, 1883",
},
};
// {
// name: string;
// born: {
// where: string;
// when: string;
// };
// died: {
// where: string;
// when: string;
// }
// }
// ν¨μμ λ°ν νμ
μΆλ‘
function square(nums: number[]) {
return nums.map((x) => x * x);
}
const squares = square([1, 2, 3, 4]);
// ^? const squares: number[]
-
μ λ νμ μΆλ‘ (λ³΄λ€ μ νν νμ μΆλ‘ μ ν΅ν΄ νμ μ€λ₯ λ°©μ§!)
-
ꡬ쑰λΆν΄ ν λΉ(λΉκ΅¬μ‘°ν ν λΉ)μ ν΅ν΄ μ§μ λ³μμ νμ μ΄ μΆλ‘ λλλ‘ νμ. (λͺ μμ νμ μ μΈX)
function logProduct(product: Product) {
const id: number = product.id;
// ~~ Type 'string' is not assignable to type 'number'
const name: string = product.name;
const price: number = product.price;
console.log(id, name, price);
}
function logProduct(product: Product) {
const { id, name, price } = product;
console.log(id, name, price);
}
맀κ°λ³μ νμ λͺ μ
-
νμ μ€ν¬λ¦½νΈλ 맀κ°λ³μμ μ΅μ’ μ¬μ©μ²κΉμ§ κ³ λ €νμ§ μλλ€
- λ³μμ νμ μ μ²μ λ±μ₯ν λ κ²°μ λλ€
- ν¨μ/λ©μλ μκ·Έλμ²μ νμ ꡬ문μ ν¬ν¨νκ³ , ν¨μ λ΄μ μ§μ λ³μμλ νμ ꡬ문μ λ£μ§ μκΈ° (μ½λ μ¬λμ΄ κ΅¬ν λ‘μ§μ μ§μ€ν μ μμ)
-
맀κ°λ³μ κΈ°λ³Έκ°μ΄ μλ κ²½μ°, νμ μ μΆλ‘ νλ€
function parseNumber(str: string, base = 10) { // ^? (parameter) base: number // ... }
νμ μ λ³΄κ° μλ λΌμ΄λΈλ¬λ¦¬
-
νμ μ§μνλ λΌμ΄λΈλ¬λ¦¬μμ
μ½λ°± ν¨μμ 맀κ°λ³μ νμ
μ μλμΌλ‘ μΆλ‘ λλ€(보ν΅)// Don't do this: app.get("/health", (request: express.Request, response: express.Response) => { response.send("OK"); }); // Do this: app.get("/health", (request, response) => { // ^? (parameter) request: Request<...> response.send("OK"); // ^? (parameter) response: Response<...> });
-
μμ
import _ from "lodash"; interface FoodItem { icon: string; category: string; price: number; } const foodItems: FoodItem[] = [ { icon: "π", category: "Fast Food", price: 5000 }, { icon: "π", category: "Fast Food", price: 8000 }, { icon: "π£", category: "Japanese", price: 12000 }, { icon: "π", category: "Japanese", price: 10000 }, { icon: "π", category: "Italian", price: 15000 }, { icon: "π₯", category: "Healthy", price: 9000 }, ]; // Lodashμ groupByλ₯Ό μ¬μ©ν λ μ½λ°± ν¨μμ 맀κ°λ³μ νμ μ΄ μλμΌλ‘ μΆλ‘ λ¨ const groupedByCategory = _.groupBy(foodItems, (item) => item.category); console.log(groupedByCategory);
νμ μ λͺ μνκ³ μΆμ κ²½μ°: κ°μ²΄ 리ν°λ΄ μ μ
- μ μμ νμ
μ λͺ
μνλ©΄, excess property check(μΆκ° μμ± μ²΄ν¬, μμ¬ μμ± μ²΄ν¬)κ° λμνλ€
- μ νμ μμ±μ΄ μλ νμ μ μ€ν λ±μ μ€λ₯
- λ³μκ° μ¬μ©λλ μκ°μ΄ μλ ν λΉνλ μμ μ μ€λ₯λ₯Ό νμ
const elmo: Product = {
name: "Tickle Me Elmo",
id: "048188 627152",
price: 28.99,
};
νμ μ λͺ μνκ³ μΆμ κ²½μ°: ν¨μ λ°νκ°
- νμ
μΆλ‘ μ΄ κ°λ₯ν μ§λΌλ, ꡬνμμ μ€λ₯κ° ν¨μλ₯Ό νΈμΆν κ³³κΉμ§ μν₯μ λ―ΈμΉμ§ μκΈ° μν΄ νμ
ꡬ문μ λͺ
μν μ μλ€.
- μλ Promise μμ μ°Έκ³ (μ€μ λ‘λ async/awaitμ ν¨κ³Όμ μΌλ‘ μ¬μ©νκΈ°, μμ΄ν 25)
const cache: { [ticker: string]: number } = {};
function getQuote(ticker: string) {
if (ticker in cache) {
return cache[ticker]; // ꡬν μ€λ₯: Promiseλ₯Ό λ°νν΄μΌ νλ€!
}
return fetch(`https://quotes.example.com/?q=${ticker}`)
.then((response) => response.json())
.then((quote) => {
cache[ticker] = quote;
return quote as number;
});
}
// ν¨μλ₯Ό νΈμΆν κ³³μμ μλ¬κ° λ°μνλ€
getQuote("MSFT").then(considerBuying);
// ~~~~ Property 'then' does not exist on type
// 'number | Promise<number>'
// μλλ λ°ν νμ
μ λͺ
μνμ¬ => μλ¬κ° λ°μν μμΉλ₯Ό μ νν νκΈ°νκΈ°
const cache: { [ticker: string]: number } = {};
function getQuote(ticker: string): Promise<number> {
if (ticker in cache) {
return cache[ticker];
// ~~~ Type 'number' is not assignable to type 'Promise<number>'
}
// ...
}
-
μ₯μ
- μ€λ₯μ μμΉλ₯Ό μ λλ‘ νμνλ€
- ν¨μ μκ·Έλμ²λ₯Ό λμ± λͺ ννκ² νλ€ (μ /μΆλ ₯ νμ λͺ μ)
- λͺ λͺ λ νμ μ¬μ©νκΈ°
interface Vector2D { x: number; y: number; } function add(a: Vector2D, b: Vector2D): Vector2D { return { x: a.x + b.x, y: a.y + b.y }; }
Things to Remember
- Avoid writing type annotations when TypeScript can infer the same type.
- νμ μ€ν¬λ¦½νΈκ° νμ μ μΆλ‘ ν μ μλ€λ©΄, νμ ꡬ문 μμ±νμ§ μκΈ°
- Ideal TypeScript code has type annotations in function/method signatures but not on local variables in their bodies.
- ν¨μ/λ©μλ μκ·Έλμ²μ νμ ꡬ문μ μμ±νκ³ , λ΄λΆ μ§μ λ³μμλ μμ±νμ§ λ§μ.
- Consider using explicit annotations for object literals to enable excess property checking and ensure errors are reported close to where they occur.
- κ°μ²΄ 리ν°λ΄κ³Ό ν¨μ λ°νμλ νμ λͺ μλ₯Ό κ³ λ €νμ.
- μΆκ°/μμ¬ μμ± μ²΄ν¬ & μλ¬κ° λ°μν μμΉμ νμλλλ‘ νκΈ°
- Don't annotate function return types unless the function has multiple returns, is part of a public API, or you want it to return a named type.
- 곡κ°λ API ν¨μμ΄κ±°λ, λͺ
λͺ
λ νμ
μ΄ νμν κ²½μ°λ₯Ό μ μΈνκ³ λ¦¬ν΄ νμ
μ λͺ
μνμ§ μμλ λ κ²
- μλ§λ 컨벀μ μ λ°λ₯Ό κ² κ°λ€
- 곡κ°λ API ν¨μμ΄κ±°λ, λͺ
λͺ
λ νμ
μ΄ νμν κ²½μ°λ₯Ό μ μΈνκ³ λ¦¬ν΄ νμ
μ λͺ
μνμ§ μμλ λ κ²