1. μΈλ±μ€ μκ·Έλμ²λ?
곡μλ¬Έμμλ μλμ κ°μ΄ μΈλ±μ€ μκ·Έλμ²μ μ¬μ© μμ μ λν΄ μ€λͺ νκ³ μλ€.
Sometimes you don’t know all the names of a type’s properties ahead of time, but you do know the shape of the values.
In those cases you can use an index signature to describe the types of possible values.
νμ μ μμ±μ λͺ¨λ₯΄μ§λ§ κ°μ ννλ₯Ό μκ³ μμ λ, μΈλ±μ€ μκ·Έλμ²λ₯Ό μ¬μ©νμ¬ νμ μ μ€λͺ ν μ μλ€.
2. μΈλ±μ€ μκ·Έλμ²μ κΈ°λ³Έ λ¬Έλ²
type Props = { [property: string]: string };
Props
νμ
μ΄ μλ€. μ¬κΈ°μμ μΈλ±μ€ μκ·Έλμ²λ [property: string]: string
μ ν΄λΉνλ€. μ΄λ¬ν μΈλ±μ€ μκ·Έλμ²λ λ€μ μΈ κ°μ§ μλ―Έλ₯Ό λ΄κ³ μλ€.
- ν€μ μ΄λ¦
- μ μμ μμμ
property
μ ν΄λΉ - ν€μ μμΉλ§ νμνλ μ©λ
- 무μν μ μλ μ°Έκ³ μ 보 - λ°λμ
property
κ° μλμ¬λ λλ€. λ€λ₯Έ λ¨μ΄λ μκ΄μλ€.
- μ μμ μμμ
- ν€μ νμ
- μ μμ μμμ 첫 λ²μ§Έ
string
μ ν΄λΉ string
,number
,symbol
μ€ νλ- 보ν΅μ
string
μ μ¬μ©
- μ μμ μμμ 첫 λ²μ§Έ
- κ°μ νμ
- μ μμ μμμ μΈλ²μ§Έ
string
μ ν΄λΉ - λͺ¨λ νμ μ΄ κ°λ₯
- μ μμ μμμ μΈλ²μ§Έ
3. μΈλ±μ€ μκ·Έλμ²μ λ¨μ
λ€μ μμ λ₯Ό ν΅ν΄ μΈλ±μ€ μκ·Έλμ²μ λ¨μ μ λν΄ μ΄ν΄λ³΄μ.
type Person = { [key: string]: string };
const person: Person = {
name: 'noah',
address: 'somewhere',
age: '30',
};
3-1. μλͺ»λ ν€λ₯Ό ν¬ν¨ν΄ λͺ¨λ ν€λ₯Ό νμ©νλ€.
key
λ string
μ΄κΈ°λ§ νλ©΄ μ΄λ ν κ°λ μ¬ μ μλ€. λλ¬Έμ name
μ΄ μλλΌ Name
μΌλ‘ ν€μ μ΄λ¦μ μ νμ¬λ μ€λ₯κ° λμ§ μλλ€.
const person: Person = {
Name: 'noah',
address: 'somewhere',
age: '30',
};
3-2. νΉμ ν€κ° νμνμ§ μλ€.
person
κ°μ²΄μ λ°λμ μ‘΄μ¬ν΄μΌ ν μμ±(ν€-κ°)μ μ ν μ μλ€. λλ¬Έμ {}
λ νμ©νλ€.
const person: Person = {};
3-3. ν€λ§λ€ λ€λ₯Έ νμ μ κ°μ§ μ μλ€.
μμ μμμμ age
λ string
μ΄ μλλΌ number
κ° λ μ ν©νλ€.
νμ§λ§ age
λ₯Ό number
λ‘ νλ©΄ νμ
μ€ν¬λ¦½νΈλ μ€λ₯λ₯Ό λνλΈλ€.
3-4. μλ μμ± κΈ°λ₯μ΄ λμνμ§ μλλ€.
μ΄λ ν μμ±μ΄ μλμ§ μ μ μκΈ° λλ¬Έμ κ°μ²΄λ₯Ό λ§λ€ λ, μλμμ± κΈ°λ₯μ μ¬μ©ν μ μλ€.
λν, κ°μ²΄λ₯Ό λ§λ€μλλΌλ κ°μ²΄μ μμ±μ μ κ·Όνλ κ³Όμ μμλ μλμμ± κΈ°λ₯μ μ¬μ©ν μ μλ€.
λ€μμ νμ μ€ν¬λ¦½νΈλ₯Ό μ¬μ©ν¨μΌλ‘μ¨ μ»μ μ μλ μλμμ± κΈ°λ₯μ μμλ€. μ¦, μΈλ±μ€ μκ·Έλμ²λ₯Ό μ¬μ©νλ©΄ μλμ κ°μ κΈ°λ₯μ μ¬μ©ν μ μλ€.
4. κ·Έλ λ€λ©΄ μΈλ±μ€ μκ·Έλμ²λ μΈμ ?
κ°λ₯νλ€λ©΄ μΈλ±μ€ μκ·Έλμ²λ³΄λ€ μ νν νμ μ μ¬μ©νλ κ²μ΄ μ’λ€. νμ§λ§ νΉλ³ν κ²½μ°μ μΈλ±μ€ μκ·Έλμ²λ₯Ό μ¬μ©ν΄μΌ νλ€. λ°λ‘ λ°νμ λκΉμ§ κ°μ²΄μ μμ±μ μ μ μμ κ²½μ°μ΄λ€.
μ νν μμ±μ μ΄λ¦μ μμ§ λͺ»νκΈ° λλ¬Έμ 미리 νμ μΌλ‘ μ ν μ μκΈ° λλ¬Έμ΄λ€.
4-1. CSV νμΌμ κ°μ²΄λ‘ λ°κΎΈκΈ°
μλμ νλ₯Ό 보μ.
μ°λ | μ μ‘°μ¬ | λͺ¨λΈ | μ€λͺ | κ°κ²© |
---|---|---|---|---|
1997 | Ford | E350 | ac abs moon | 3000.00 |
1999 | Chevy | Venture Extended Edition | 4900.00 | |
1999 | Chevy | Venture Extended Edition | Very Large | 5000.00 |
1996 | Jeep | Grand Cherokee | MUST SELL! air moon roof loaded | 4799.00 |
첫 λ²μ§Έ μ΄μ headerμ΄λ©° μ΄λ μ΄λ€ λ°μ΄ν°λ₯Ό κ°μ Έμ ννν κ²μΈμ§μ λ°λΌ λ¬λΌμ§ μ μλ€. μ¦, headerμ λ΄μ©μ΄ λ λ§μμ§ μλ, μ μ΄μ§ μλ νΉμ λ€λ₯Έ μ΄λ¦μΌλ‘ λ°λ μ μλ€. μ΄λ° κ²½μ° μ°λ¦° headerκ° λ¬΄μμΈμ§ νμ μ§μ μ μλ λ¬Έμ κ° μκΈ΄λ€. μ΄λ° λ°μ΄ν°λ₯Ό λμ λ°μ΄ν°
λΌκ³ νλ©° λμ λ°μ΄ν°
λ₯Ό λ€λ£¨λ κ²½μ° μΈλ±μ€ μκ·Έλμ²λ₯Ό ν΅ν΄ νμ
μ μ ν μ μλ€.
μμ κ°μ νλ₯Ό CSV νμΌ νμμΌλ‘ λ°κΎΈλ©΄ μλμ κ°λ€.
CSV(μμ΄: comma-separated values)λ λͺ κ°μ§ νλλ₯Ό μΌν(,)λ‘ κ΅¬λΆν ν μ€νΈ λ°μ΄ν° λ° ν μ€νΈ νμΌμ΄λ€
const exampleCSV = `μ°λ,μ μ‘°μ¬,λͺ¨λΈ,μ€λͺ
,κ°κ²©
1997,Ford,E350,ac abs moon,3000.00
1999,Chevy,Venture Extended Edition,,4900.00
1999,Chevy,Venture Extended Edition,Very Large,5000.00
1996,Jeep,Grand Cherokee,MUST SELL! air moon roof loaded,4799.00`;
κ° μ΄μ κ°μ headerμ μ΄λ¦κ³Ό 맀ννλ κ°μ²΄λ‘ λνλ΄μ΄ 보μ.
function parseCSV(input: string): { [columnName: string]: string }[] {
const lines = input.split('\n'); // κ° μ΄μ λλλ€.
const [header, ...rows] = lines; // 첫λ²μ§Έ μ΄μ header, λλ¨Έμ§λ rowsλ‘ λλλ€.
const headerColumns = header.split(','); // headerμ λ΄μ©μ ,λ₯Ό κΈ°μ€μΌλ‘ λλλ€.
// μ κ³Όμ μ ν΅ν΄ λμ¨ κ°λ€μ΄ μ νν μ΄λ€ κ°μΈμ§ λ°νμ μ΄μ μ λͺ¨λ₯΄κΈ° λλ¬Έμ μΈλ±μ€ μκ·Έλμ²λ₯Ό μ¬μ©νλ€.
return rows.map((rowStr) => {
const row: { [columnName: string]: string } = {}; // λ¦¬ν΄ ν κ°
rowStr.split(',').forEach((cell, i) => {
row[headerColumns[i]] = cell; // κ° νμ λ§λ headerμ μ΄λ¦μ 맀ν½νμ¬ rowμ μΆκ°νλ€.
});
return row; // λ°ν
});
}
λ€μμ κ²°κ³Όκ°μ΄λ€.
parseCSV(exampleCSV);
[
{
μ°λ: '1997',
μ μ‘°μ¬: 'Ford',
λͺ¨λΈ: 'E350',
μ€λͺ
: 'ac abs moon',
κ°κ²©: '3000.00',
},
{
μ°λ: '1999',
μ μ‘°μ¬: 'Chevy',
λͺ¨λΈ: 'Venture Extended Edition',
μ€λͺ
: '',
κ°κ²©: '4900.00',
},
{
μ°λ: '1999',
μ μ‘°μ¬: 'Chevy',
λͺ¨λΈ: 'Venture Extended Edition',
μ€λͺ
: 'Very Large',
κ°κ²©: '5000.00',
},
{
μ°λ: '1996',
μ μ‘°μ¬: 'Jeep',
λͺ¨λΈ: 'Grand Cherokee',
μ€λͺ
: 'MUST SELL! air moon roof loaded',
κ°κ²©: '4799.00',
},
];
4-2. μ΄(header) μ΄λ¦μ μκ³ μλ κ²½μ°
νμ§λ§ μ΄ μ΄λ¦μ μκ³ μλ νΉμ ν μν©μ΄λΌλ©΄ 미리 μ μΈν΄ λ νμ μΌλ‘ λ¨μΈλ¬Έμ μ¬μ©νλ κ²μ΄ μ’λ€.
type Product = {
μ°λ: string;
μ μ‘°μ¬: string;
λͺ¨λΈ: string;
μ€λͺ
: string;
κ°κ²©: string;
};
const products = parseCSV(exampleCSV) as unknown as Product;
5. μ°κ΄ λ°°μ΄μμμ μΈλ±μ€ μκ·Έλμ²
μ°κ΄ λ°°μ΄μ΄λ? ν€ νλμ κ° νλκ° μ°κ΄λμ΄ μμΌλ©° ν€λ₯Ό ν΅ν΄ μ°κ΄λλ κ°μ μ»μ μ μλ μλ£κ΅¬μ΄λ€.
μλ₯Ό λ€μ΄ λ¬Έμμ΄ λ΄μμ λ¨μ΄λ₯Ό κΈ°μ€μΌλ‘ μͺΌκ°μ΄, λ¨μ΄κ° λͺ λ² λ±μ₯νλμ§λ₯Ό κ°μ²΄λ‘ νννκ³ μ νλ€. μ΄λ, ν€λ λ¨μ΄κ° λ κ²μ΄κ³ κ°μ λ¨μ΄κ° λ¬Έμμ΄μμ λ±μ₯ν μκ° λλ€.
"Objects have a constructor"μ΄λΌλ λ¬Έμμ΄μ λ°νμΌλ‘ κ°μ²΄λ₯Ό λ§λλ©΄ μμλλ κ°μ²΄λ λ€μκ³Ό κ°λ€.
{
Objects: 1;
have: 1;
a: 1;
constructor: 1;
}
μ΄μ κ°μ κ°μ²΄λ₯Ό μμ±νλ ν¨μλ₯Ό μΈλ±μ€ μκ·Έλμ²(5-1) λλ Map νμ (5-2)μ μ΄μ©νμ¬ λ§λ€μ΄λ³΄μ.
5-1. μΈλ±μ€ μκ·Έλμ²λ₯Ό μ¬μ©ν ν¨μ
function countWords(text: string) {
const counts: { [word: string]: number } = {};
const words = text.split(/[\s,.]+/);
words.forEach((word) => {
counts[word] = ([word] || 0) + 1;
});
return counts;
}
μ ν¨μλ₯Ό ν΅ν΄ κ²°κ³Όλ₯Ό μ΄ν΄λ³΄λ©΄ λ€μκ³Ό κ°λ€.
{
Objects: 1,
have: 1,
a: 1,
constructor: 'function Object() { [native code] }1'
}
constructor
λΆλΆμ΄ μ΄μνλ€. μ΄λ constructor
μ μ΄κΈ°κ°μ΄ undefined
κ° μλλΌ Object.prototype
μ μλ μμ±μ ν¨μμ΄κΈ° λλ¬Έμ΄λ€.
5-2. Map νμ μ μ¬μ©ν ν¨μ
function countWords(text: string) {
const counts: Map<string, number> = new Map(); // Map νμ
μ μ¬μ©
const words = text.split(/[\s,.]+/);
words.forEach((word) => {
counts.set(word, (counts.get(word) || 0) + 1);
});
return counts;
}
Map(4) { 'Objects' => 1, 'have' => 1, 'a' => 1, 'constructor' => 1 }
μνλ κ²°κ³Όλ₯Ό λ³Ό μ μλ€.
6. νμ μ μ‘°κΈ λ μ’νκΈ°
λ€μμ μν©μ κ°μ ν΄ λ³΄μ.
- λ°μ΄ν°μ a, b, c, d, eμ ν€κ° μλ€.
- a, b, c, d, eλ λͺ¨λ νμκ° μλλ€.
- λ°μ΄ν°μ μ νν μΌλ§λ§νΌ ν€κ° λ€μ΄μλμ§ λͺ¨λ₯Έλ€.
μμ κ°μ μν©μμ μΈλ±μ€ μκ·Έλμ²λ₯Ό μ¬μ©ν μ μλ€.
type Row = { [key: string]: string };
νμ§λ§ key
κ° string
μ΄λΌλ κ²μ λ무 κ΄λ²μνλ€. λλ¬Έμ κ΄λ²μν λ²μλ₯Ό μ’νλ κ²μ΄ μ’λ€.
μ΄λ₯Ό μν λ°©λ²μ μμ보μ.
6-1. Record
Record
λ λ€μκ³Ό κ°μ ννλ₯Ό κ°μ§κ³ μλ€.
// lib.es5.d.ts μμμ μ μ
type Record<K extends keyof any, T> = {
[P in K]: T;
};
type Record<K extends string | number | symbol, T> = { [P in K]: T; }
λ¨Όμ ,
λ₯Ό κΈ°μ€μΌλ‘ μΌμͺ½μ΄ key
, μ€λ₯Έμͺ½μ΄ value
μ΄λ€. κ·Έλ¦¬κ³ K
μ κ°μ string
, number
, symbol
μ€ νλμΌ μλ μκ³ λΆλΆ μ§ν©μΌ μλ μλ€.
μ΄λ¬ν Record
λ₯Ό μ¬μ©νμ¬ μΈλ±μ€ μκ·Έλμ²λ₯Ό ꡬννλ©΄ μλμ κ°λ€.
type Row = Record<string, string>;
λ§€μ° κ°λ¨νλ€. νμ§λ§ μμ§ μμ¬μ΄ μ μ λ¨μμλ€. ν€μ κ°μ΄ string
μ΄κΈ° λλ¬Έμ μμ§ κ΄λ²μνλ€. μ΄λ₯Ό 쑰건μ λ§κ² λ°κΎΈμ΄ 보μ.
쑰건μ a, b, c, d, e ν€κ° μλ€κ³ νμμΌλ string
λμ μ λμ¨μΌλ‘ ννν΄ λ³΄μ.
type Row = Record<'a' | 'b' | 'c' | 'd' | 'e', string>;
// type Row1 = {
// a: string;
// b: string;
// c: string;
// d: string;
// e: string;
// };
'a' | 'b' | 'c' | 'd' | 'e'
λ string
μ λΆλΆ μ§ν©μ΄λ―λ‘ κ°λ₯νλ€.
νμ§λ§ μμ§ μμ¬μ΄ μ μ΄ μλ€. μμ§ λͺ¨λ ν€λ€μ΄ νμκ°μ΄λΌλ κ²μ΄λ€. 쑰건μ 보μλ©΄ λͺ¨λ νμκ°μ΄ μλλ€. μ΄λ₯Ό ν΄κ²°νκΈ° μν΄μ μμ Partial
λ₯Ό λΆμ΄λ©΄ λλ€.
type Row = Partial<Record<'a' | 'b' | 'c' | 'd' | 'e', string>>;
// type Row = {
// a?: string | undefined;
// b?: string | undefined;
// c?: string | undefined;
// d?: string | undefined;
// e?: string | undefined;
// }
μ΄λ‘μ¨ string
μ΄λΌλ κ΄λ²μν λ²μλ₯Ό μ’νλ©΄μ 쑰건μ νμ
μ λ§μ‘±ν μ μλ€.
string
μ΄λΌλ κ΄λ²μν λ²μλ₯Ό μ λμ¨μ μ¬μ©νμ¬ λ²μλ₯Ό μ’νλ©΄ λ μ΄μ μΈλ±μ€ μκ·Έλμ²λΌκ³ λΆλ₯Ό μ μλ κ² μλκΉ?
6-2. 맀νλ νμ
λ¨Όμ λ€μμ 맀νλ νμ μ μ¬μ©ν μΈλ±μ€ μκ·Έλμ²μ΄λ€.
type Row = { [k in string]: string };
μ¬μ€ 맀νλ νμ
μ μ’ λ μ½κ² μ¬μ©νλ λ°©λ²μ΄ Record
μ΄λ€. νμ§λ§ 맀νλ νμ
μ μ¬μ©νλ©΄ λ μ μ°νκ² νμ
μ μ ν μ μλ€.
μλ₯Ό λ€μ΄ μμ a, b, c, d, eμ ν€ μ€ d
λ string
μ΄ μλλΌ number
λΌκ³ κ°μ ν΄ λ³΄μ. μ΄λ λ€μκ³Ό κ°μ΄ μ½λλ₯Ό μμ±νλ©΄ λλ€.
type Row = {
[k in 'a' | 'b' | 'c' | 'd' | 'e']: k extends 'd' ? number : string;
};