如何在打字稿中没有运行时副作用的情况下进行精确的类型检查?
Posted
技术标签:
【中文标题】如何在打字稿中没有运行时副作用的情况下进行精确的类型检查?【英文标题】:How to do an exact type checking without having runtime side effects in typescript? 【发布时间】:2021-09-27 18:16:59 【问题描述】:我是打字稿的新手。看简单的例子:
// My bird collection
interface Birds
name: string;
color: string;
db.find(colour: "black").limit(1)
// here, the statement is using "colour" instead of "color".
// I want to prevent these scenarios. So, I tried
db.find(["colour" as keyof Birds]: "black") // I thought this would produce error. But this will not.
// What I'm doing:
const colorKey: keyof Birds = "color"; // using "colour" gives error here, as expected.
db.find([colorKey]: "black")
// but this is producing a lot of variables and runtime code. Is there any cleaner workaround?
在与多个团队和项目合作时,这同样适用于其他情况
// types published by Team A/Project A.
type Collections = "Birds"|"Cats";
// these types consumed by Team B/Project B like:
db.collection("cats" as Collections) // no errors. But I'm using "cats" instead of "Cats"
const catCollectionKey: Collections = "Cats";
db.collection(catCollectionKey) // OK
问题:如何在没有运行时副作用的情况下进行精确的类型检查?
playground
我明白为什么 as
没有产生任何错误。 但是有没有更简洁的解决方法/语法/操作符呢?喜欢
db.collection(<Exactly<Collections>>"cat") // ts-error. "cat" is not assignable to "Cats"|"Birds"
// or
db.collection("cat" strictlyAs Collection) // ts-error. "cat" is not assignable to "Cats"|"Birds"
【问题讨论】:
db.find(color: "black" as Birds).limit(1)
你需要通过类型断言告诉 ts 编译器你的对象是Birds
你没有创建很多变量,那些是类型定义。 Typescript 使用它们来理解你的代码,一旦代码编译所有它们类型和东西就会消失。所以不用担心。不幸的是,这是 typescript 的缺点之一。我建议您首先了解不同的类型、接口、模块、名称空间是什么。在编写实际代码之前了解它们是什么以及如何使用它们
@AlirezaAhmadi 这是我的问题:在color: "black" as Birds
中,color: "black"
不能正确代表Bird
,您还需要name
。但是您仍然可以毫无错误地使用它。我正在寻找一种类似于as
但更严格的运算符/方式。因此,当我使用 color: "black" as Birds
时,我可能会收到类似 color: "black" is not assignable to Birds, property "name" is missing
的错误
【参考方案1】:
内联类型检查:
db.find(colour: "black" as Partial<Bird>).limit(1)
在您的"cats" as Collection
示例中,您告诉打字稿“猫”是一个集合,而实际上不是。这可以防止引发类型警告。
这可以通过Here 建议的类型检查功能来解决,但它有运行时副作用:
function asType<T>(value: T)
return value;
;
然后像这样使用:
db.collection(asType<Collection>("cats"))
但是这样做意味着每个人每次使用 find()
或 collection()
函数时都需要键入断言输入,这些函数可能会被忘记或使用错误的类型断言。
考虑将函数的参数改为类型化。
【讨论】:
请注意这不是我要找的答案。我使用db:any
作为示例目的(因为没有收到“var db not defined”错误)。我已经更新了操场上的 cmets。我的问题是有没有简单的方法来强制执行类型检查。类似于birdVar as Bird
中as
的目的——但更严格。因此,请删除此答案,因为它具有误导性。
您可以在线获得相同的行为。但是如果你告诉find()
函数期望什么类型,你不必每次使用它时都这样做。我会根据您的需要更改答案。
此解决方案有效。但这有运行时的副作用。为了实现类型检查,我们在运行时代码中添加了一个函数。
没错,示例前面的链接来自 GitHub 上的 TypeScript 问题跟踪器。您可以在那里订阅,以便在将此功能添加到语言时收到通知。这个问题是在 5 年前创建的,所以不要抱太大希望。以上是关于如何在打字稿中没有运行时副作用的情况下进行精确的类型检查?的主要内容,如果未能解决你的问题,请参考以下文章