【发布时间】:2021-04-13 15:26:44
【问题描述】:
在设置类中,我有一个获取值的方法,如果找不到给定的键,则返回一个可选的默认值:
/**
* Returns the value stored at the given key, which can have the form `qualifier.subKey`.
*
* @param key The key to look up.
* @param defaultValue An optional value to be returned if the there's no value at the given key or the key doesn't
* exist at all.
*
* @returns If a return value is given the return type is the same as that of the default value. Otherwise it's
* either undefined or the same as the type found at the given key.
*/
public get<T>(key: string, defaultValue: T): T;
public get(key: string): any;
public get<T>(key: string, defaultValue?: T): T | undefined {
const { target, subKey } = this.objectForKey(key, false);
if (!target || !subKey) {
return defaultValue;
}
return target[subKey] as T ?? defaultValue;
}
这个实现给了我没想到的返回类型。考虑这个调用:
const removeIdleTime = settings.get("workers.removeIdleTime", 60);
变量removeIdleTime 不是我所期望的数字类型,而是60 类型。我可以明确地将<number> 用作get 的模板/通用参数,然后结果就可以了,但是让Typescript 推断出正确的类型会更酷。必须改变什么来实现这一点?
更新
我刚刚在 Typescript 中找到了关于 type widening 的描述(在写这个问题的时候我不知道正确的术语)。事实证明,将get 的结果分配给可变变量时,类型被扩展了。否则它保持为文字类型。
虽然这是有趣的信息,但它对这个问题没有帮助,因为如果在初始分配后没有更改任何 let,linter 通常会将它们转换为 const。
【问题讨论】:
-
键是一组有限的值吗?如果是这样,那么您希望泛型为 K extends keyof SomeType ,其中键为 K,默认值为 SomeType[K]。
-
也许我理解错了,但问题的症结在于如何从文字类型(
60)到基本类型(number)? -
有趣,不确定在哪个版本中发生了变化,但之前要“触发”文字类型推断,您必须在泛型类型约束 github.com/microsoft/TypeScript/pull/24310 中具有原始类型。但现在已经不是这样了typescriptlang.org/play?#code/…
-
@Etheryte 无需提交错误报告。行为改变是有意的。请参阅 Aleksey 的链接,其中 Anders 解释了其背后的基本原理。
-
在某些情况下会出现问题:假设您从存储中获取了一个数字值并使用默认值。文字类型是 1,当你测试它的 2 时,你会得到一个警告,这个比较总是错误的,因为 1 和 2 没有重叠。
标签: typescript