繁体   English   中英

如何在 TypeScript 中对地图和集合强制执行更严格的输入?

[英]How to enforce stricter typing on Maps and Sets in TypeScript?

如果我像这样创建 map:( 操场

const x = new Map();
const y = x.get("foo");
y.thisDoesntExist();

我希望在最后一行出现错误(至少在严格模式下),因为我从未指定new Map的键和值类型应该是什么。 相反,map 的类型是Map<any, any> ,所以我没有收到任何警告。 Set<any>也是如此。

我正在移植一个 JavaScript 项目,所以像这样的案例到处都是,很难判断哪里缺少类型。

有没有办法配置 typescript 以便在我尝试在没有 generics 的情况下实例化集合和映射时警告我? 或者至少让 generics 默认为Set<unknown>

无参数Map 构造函数具有Map<any, any>返回类型:

interface MapConstructor {
    new(): Map<any, any>;
    // ...
}

因此noImplicitAny在这里没有帮助(类型是显式的)

可以做的是用Map<unknown, unknown>覆盖它( 声明合并):

interface MapConstructor {
    new(): Map<unknown, unknown>;
}

现在y.thisDoesntExist(); 会报错。

操场


Set的行为不同,因为它的构造函数定义为:

new <T = any>(values?: readonly T[] | null): Set<T>;

因此,如果未提供泛型类型和值 - 类型将是unknown的:

const s = new Set(); // s: Set<unknown>

更新(2022 年 6 月 28 日)

在使用 JavaScript + JSDoc 时,似乎简单地使用never而不是unknown就足以使类型变得严格。 不知道为什么我之前必须跳过这么多圈,但现在我只是在使用。

interface SetConstructor {
    new(): Set<never>;
}

interface MapConstructor {
    new(): Map<never, never>;
}

旧答案

要使用 JSDoc 在 js 中使用 ts,您可以在新的.d.ts中添加以下内容

interface MapConstructor extends Omit<MapConstructor, 'new'> {
    new<K = unknown, V = unknown>(entries?: readonly (readonly [K, V])[] | null): Map<K, V>;
}

interface SetConstructor {
    new <T = unknown>(values?: readonly T[] | null): Set<T>;
}

在 JavaScript 中,generics 在未设置时默认为any ( #14907 ),因此您必须明确将其默认设置为unknown 因此,在使用 JavaScript 时,空构造函数不起作用。

MapConstructorlib.es2015.collection.d.ts中有一个空的new(): Map<any, any>条目。 因此,为了删除它,我们使用Omit<MapConstructor, 'new'> 然后我们可以指定已经存在的相同构造函数,除了显式unknown作为默认值。

SetConstructor没有空的new()条目,但它确实有new <T = any> ,所以我们也必须用unknown覆盖它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM