仅供参考,作为string index signature 之类的替代品
interface FutureProjection {
[k: string]: number
}
它可以接受任何密钥:
declare const f: FutureProjection
f.oopsiedaisy = 123; // no compiler error
人们可能会考虑使用 TypeScript 4.4 中引入的 template string pattern index signature 来仅接受以 "month" 开头并后跟类似数字的字符串:
interface FutureProjection {
[k: `month${number}`]: number
}
declare const f: FutureProjection
f.oopsiedaisy = 123; // error
f.month11 = 456; // okay
f.month1234567 = 789; // this is also okay, any number is accepted
如果您这样做,编译器将自动允许您使用适当构造的 template literal string 索引到 FutureProjection:
function functionToSetMonthData(currentDate: string, futureDate: string,
projection: FutureProjection, amount: number
): FutureProjection {
const monthNum = calculateMonthNum(currentDate, futureDate);
projection[`month${monthNum}`] = amount; // okay
return projection;
}
请注意,这并不能完全满足仅接受 month1 到 month12 的目的。您可以决定将number 替换为数字literal types 的union,
type MonthNumber = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
interface FutureProjection extends Record<`month${MonthNumber}`, number> { }
declare const f: FutureProjection
f.oopsiedaisy = 123; // error
f.month11 = 456; // okay
f.month1234567 = 789; // error
这很棒;不幸的是,您很难让编译器相信您产生number 的任何数学运算实际上都在产生MonthNumber,因为它并没有真正在类型级别进行数学运算(请参阅microsoft/TypeScript#15645):
declare const i: MonthNumber;
const j: MonthNumber = 13 - i; // error, even though this must be safe
const k: MonthNumber = ((i + 6) % 12) || 12; // error, ditto
所以你会发现自己无论如何都在做不安全的断言以及其他一些解决方法:
function calculateMonthNum(currentDate: string, futureDate: string): MonthNumber {
return (((((new Date(futureDate).getMonth() - new Date(currentDate).getMonth())
% 12) + 12) % 12) || 12) as MonthNumber // <-- assert here
}
function functionToSetMonthData(currentDate: string, futureDate: string,
projection: FutureProjection, amount: number
): FutureProjection {
const monthNum = calculateMonthNum(currentDate, futureDate);
projection[`month${monthNum}` as const] = amount; // <-- const assert here
return projection;
}
const f = {} as FutureProjection; // assert here
for (let i = 1; i <= 12; i++) f[`month${i as MonthNumber}`] = 0; // assert here
所以我觉得你最好用`month${number}`。
Playground link to code