function pluck<T, K extends keyof T>(record: T[], key: K): T[K][] {
return record.map(r => r[key]);
}
type RecordingType = 'studio' | 'live';
interface Album {
artist: string;
title: string;
releaseDate: Date;
recordingType: RecordingType;
}
declare let albums: Album[];
pluck(albums, 'releaseDate'); // Type is Date[]
pluck(albums, 'artist'); // Type is string[]
pluck(albums, 'recordingType'); // Type is RecordingType[]
pluck(albums, 'recordingDate');
// ~~~~~~~~~~~~~~~ Argument of type '"recordingDate"' is not
// assignable to parameter of type ...
type Expression1 = any;
type Expression2 = number | string | any[];
type Expression4 = number | string | CallExpression;
type CallExpression = MathCall | CaseCall | RGBCall;
interface MathCall {
0: '+' | '-' | '/' | '*' | '>' | '<';
1: Expression4;
2: Expression4;
length: 3;
}
interface CaseCall {
0: 'case';
1: Expression4;
2: Expression4;
3: Expression4;
length: 4 | 6 | 8 | 10 | 12 | 14 | 16 // etc.
}
interface RGBCall {
0: 'rgb';
1: Expression4;
2: Expression4;
3: Expression4;
length: 4;
}
const tests: Expression4[] = [
10,
"red",
true,
// ~~~ Type 'true' is not assignable to type 'Expression4'
["+", 10, 5],
["case", [">", 20, 10], "red", "blue", "green"],
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Type '["case", [">", ...], ...]' is not assignable to type 'string'
["**", 2, 31],
// ~~~~~~~~~~~~ Type '["**", number, number]' is not assignable to type 'string
["rgb", 255, 128, 64],
["rgb", 255, 128, 64, 73]
// ~~~~~~~~~~~~~~~~~~~~~~~~ Type '["rgb", number, number, number, number]'
// is not assignable to type 'string'
];
const okExpressions: Expression4[] = [
['-', 12],
// ~~~~~~~~~ Type '["-", number]' is not assignable to type 'string'
['+', 1, 2, 3],
// ~~~~~~~~~~~~~~ Type '["+", number, ...]' is not assignable to type 'string'
['*', 2, 3, 4],
// ~~~~~~~~~~~~~~ Type '["*", number, ...]' is not assignable to type 'string'
];
코드를 너무 정밀하게 만드려던 시도가 과했고 그로 인해 코드가 오히려 부정확해졌습니다.
<이펙티브 타입스크립트> (댄 밴더캅 지음, 장원호 옮김, 인사이트, 2021)