编辑
由于时间的推移,这个问题 已经失去了它的有效性,从评论和答案中似乎可以看出这一点。尽管最初出现,但它不是这个人的骗局。
我有一个通过以下签名工作的翻译功能。
getI18n(id: string) : string { ... }
Run Code Online (Sandbox Code Playgroud)
我注意到输入以下内容有点乏味。
const titles = [
this.util.getI18n("Donkey"),
this.util.getI18n("Monkey"),
...
this.util.getI18n("Wonkey")
];
Run Code Online (Sandbox Code Playgroud)
我更喜欢使用这样的东西。
const titles = this.util.getI18n(["Donkey", "Monkey", ..., "Wonkey"]);
Run Code Online (Sandbox Code Playgroud)
所以我引入了一个接受string和string[]的函数,其签名如下。
getI18n(id: string | string[]) : string | string[] { ... }
Run Code Online (Sandbox Code Playgroud)
这感觉很天才,直到我注意到我必须为愚蠢的 Typescript 解释结果是字符串而不是一些笨拙的巨型字符串或字符串数组,最终得到这个(对于非数组翻译)。
someValue.replace("xxx", this.util.getI18n("Donkey") as string);
Run Code Online (Sandbox Code Playgroud)
有没有办法为 TypeScript 解释输出是字符串,即使在其他情况下它可能是string[]?
您可以通过泛型类型属性来实现效果。考虑:
function getI18n<A extends string[] | string>(id: A): A {
return id; // example implementation
}
const arr = getI18n(['a', 'b']) // arr is string[]
const str = getI18n('a') // str is string
Run Code Online (Sandbox Code Playgroud)
由于该解决方案适用于 id 函数,问题始于任何实现,TS 抱怨类型,好像唯一的方法是传递参数而不进行任何修改。考虑:
function getI18n<A extends string[] | string>(id: A): A {
if (typeof id === 'string') {
return id.concat('suffix') as A;
} else {
return (id as string[]).map(x => x.concat('suffix')) as A;
}
}
Run Code Online (Sandbox Code Playgroud)
该解决方案效果很好,但我们需要考虑一些事情:
最后一点问题可以在下面的例子中查看:
const str = getI18n('a') // str is type "a"
Run Code Online (Sandbox Code Playgroud)
所以输出类型是“a”,但在示例中实现结果将是一个字符串“asuffix”,所以类型是错误的。
我想在整个主题中添加一件事。我们需要拥有这种多态输入的事实通常是通过常见的 JS 方法继承的,这样的事情在历史上被认为是良好的做法。但在现实中,具有特定输入的功能会更好,它会产生更少的混乱和问题。
创建具有单态类型的函数。
function getI18n(ids: string[]): string[] {
return ids.map(id => id + "suffix");
}
const arr = getI18n(['a', 'b'])
const str = getI18n(['a'])
Run Code Online (Sandbox Code Playgroud)
就那么简单。该方法的好处:
将字符串放入数组括号中确实没有成本。
除了泛型之外,您还可以使用函数重载
function getI18n(id: string[]): string[];
function getI18n(id: string): string;
function getI18n(id: string | string[]): string | string[] {
if (typeof id === 'string') {
return id + '_title';
}
return id.slice();
}
const title = getI18n('test'); // const title: string
const titles = getI18n(['a', 'b', 'c']); // const titles: string[]
Run Code Online (Sandbox Code Playgroud)
有关此功能的官方文档链接:函数重载
| 归档时间: |
|
| 查看次数: |
353 次 |
| 最近记录: |