TypeScript 允许使用可选的索引签名(为了精确的OptionalPropertyTypes)

mlmc2os5  于 4个月前  发布在  TypeScript
关注(0)|答案(7)|浏览(60)

Bug报告

🔎 搜索词

exactOptionalPropertyTypesstrictoptionalPropertiesPartial 索引签名字典记录

🕗 版本和回归信息

  • 这个行为在每个我尝试的版本中都是这样的,我也查看了关于 exactOptionalPropertyTypes 的FAQ条目。

⏯ Playground链接

带有相关代码的Playground链接

💻 代码

type MyRecord = { x: string; z: string };

const r: Partial<MyRecord> = {
    x: "y",
    // Error as expected ✅
    z: undefined,
};

type MyDict = { [key: string]: string };

const d: Partial<MyDict> = {
    x: "y",
    // Expected error but got none ❌
    z: undefined,
};

🙁 实际行为

请参阅上面的代码注解。

🙂 预期行为

请参阅上面的代码注解。
这个行为在 #44524 中被简要讨论过,并且在 #44421(评论)中提到。

zsbz8rwp

zsbz8rwp1#

这实际上是一个设计限制。我们不支持可选索引签名的概念(即在索引签名的声明中无法指定 ? ),在 --exactOptionalPropertyTypes 之前,确实没有理由这样做。从本质上讲,索引签名表示可选属性,而所有可选索引签名所做的只是将 undefined 添加到类型中——你可以直接手动完成。然而,有了 --exactOptionalPropertyTypes ,我们现在有两种类型的 undefined ,唯一获取缺失属性类型的方法是通过属性声明上的 ? 修饰符。出于这个原因,我们可能需要考虑在索引签名上支持 ? 修饰符。

nqwrtyyt

nqwrtyyt2#

是否有方法检测到一个类型被索引(但未Map)作为解决方法?
更新:我最终得到了以下内容。如果有人遇到这个问题并且有改进的想法,请告诉我:

type IsIndexed<T> = {
    [IndexType in string | number | symbol]: IndexType extends keyof T
        ? true
        : false;
}[keyof T];

interface Test {
    prop: string;
}
const value: IsIndexed<string> = false;
const object: IsIndexed<Test> = false;
const mapped: IsIndexed<Record<keyof Test, unknown>> = false;
const indexed: IsIndexed<Record<keyof Test | string, unknown>> = true;
const indexedWithoutString: IsIndexed<Record<number | symbol, unknown>> = true;
sqserrrh

sqserrrh3#

如果我们能够在 Partial 类型的数组中使用 Object.values,而不包含 undefined,那将是非常好的。我喜欢用 undefined 标记索引签名值,但当我在对象上使用 Object.values 时,我必须过滤掉那些并不存在的 undefined 值。例如(链接):

// Use Partial since ranges might not be set for all keys
type RangeDictionary = Partial<{ [key: string]: { start: number, end: number }}>;

function getRangeEnds(rangeDictionary: RangeDictionary) {
  // TypeScript wants me to consider the possibility that range is undefined here
  return Object.values(rangeDictionary).map(range => range.end);
}
vhmi4jdf

vhmi4jdf4#

解构和部分赋值也不起作用:

function foo(v: Partial<{ a: number }>) {}

function boo({ a }: Partial<{ a: number }>) {
	// Argument of type '{ a: number | undefined; }' is not assignable 
	// to parameter of type 'Partial<{ a: number; }>' with 'exactOptionalPropertyTypes: true'
	foo({ a })
}

playground
这应该在这里跟踪,还是应该是一个不同的问题?

vptzau2j

vptzau2j5#

我遇到了相同的问题,在任何地方都找不到解决方案。有人成功解决了吗?

pepwfjgg

pepwfjgg6#

这不仅仅是为了exactOptionalPropertyTypes!它还将使在具有索引签名的类型的对象上设置属性更加安全。目前,TS通常只是让你在具有[key: string]: ... | undefined的类型上获取和设置未知属性,因为那涵盖了所有未知属性。例如,在接口中重命名或删除字段后,我通常不会收到TS错误,提示我在哪里设置了该字段以进行重命名或删除。
这可能导致我只在运行时才发现的错误。能够在接口中使用[key: string]?: ...(就像[Key in string]?: ...一样,它不能在接口中使用)将防止这种情况,无论是否使用exactOptionalPropertyTypes。目前,如果我想要使用接口(它们是enforced by TS's stylistic ESLint config,而我的项目现在遗憾地使用了),我没有其他选择。

g6ll5ycj

g6ll5ycj7#

我有一个相关的建议-是否可以使用noUncheckedIndexAccess=true仅报告记录(但不包括数组)?

相关问题