搜索词
会话类型,可变类型,有状态类型
建议
会话类型用于描述有状态协议(即会话)。静态类型检查可以防止因调用方法顺序错误而造成的失误。这对于提供公共API以引导用户尤其有帮助。
一个简单的例子是一个需要认证的API:首先,你需要调用一个 login
方法,然后你才被允许调用其他方法,例如 getPrivateData
。
会话类型在类型系统中仍然是一个相对模糊的功能。据我所知,没有主要的编程语言默认支持它。因此,Typescript可能是其中的创新者;)有很多学术材料,但恐怕没有面向公众的材料。这似乎是一篇相当易读的介绍: http://www.simonjf.com/2016/05/28/session-type-implementations.html
用例
会话类型的最常见用例是有状态连接协议(即会话)。例如,处理文件访问的类,它将确保在写入文件之前打开文件。
目前,这些用例要么由运行时检查覆盖,要么由“流畅API”的设计实现。然而,这两种解决方案都不充分:
运行时检查等同于动态类型,可能在重构时被遗漏。它们无法静态分析以提供IDE支持。
使用流畅API,你会失去许多通用语言能力,如返回值、控制流等。如果流畅API实现为“单类型”,则完全没有类型检查,必须通过RuntimeExceptions进行类型检查。
当实现“类型化的流畅API”(即返回与 this
不同的对象),可能会变得浪费资源,因为许多对象没有理由被创建,而且代码也会变得相当复杂。
示例
对扑克游戏(德州扑克)进行建模:
const pokerGame = new PokerGame();
await pokerGame.receiveCards();
const cards = pokerGame.getMyCards();
if(ai.iWantToBet()){
await pokerGame.bet() // may only be called once and is exclusive with .pass(), .fold()
}else if(ai.iWantToPass()){
await pokerGame.pass() // may only be called once and is exclusive with .bet(), .fold()
}else if(ai.iWantToFold()){
await pokerGame.fold() // may only be called once and is exclusive with .bet(), .pass()
}
await pokerGame.nextRound() // only method which is allowed to be called by now.
const publicCards = pokerGame.getPublicCards(); // can only be called after nextRound() has been called
// and so on...
作为语法,我们可以使用类型Assert语法( x as Type
),因为这基本上与在函数调用中设置 this
的类型相同。
也许有人可以将语法扩展到设置参数的类型,但我将其留给大家讨论..
interface RoundFinished {
nextRound();
}
interface RoundStart {
bet(): this as RoundFinished;
pass(): this as RoundFinished;
fold(): this as GameFinished;
}
interface GameFinished {
getResults();
}
class PokerGame {
bet(): this as RoundFinished {
// code
// after the function exits, "this" is now typechecked as "RoundFinished" (without having to use "fluent API")
}
nextRound(): this as RoundStart {
// and so on..
}
}
检查清单
我的建议满足以下准则:
- 这不会对现有的TypeScript/JavaScript代码造成破坏性更改
- 这不会改变现有JavaScript代码的运行时行为
- 这可以在不根据表达式的类型生成不同JS的情况下实现
- 这不是一个运行时特性(例如库功能、JavaScript输出非ECMAScript语法等)
- 这个特性将与其他 TypeScript's Design Goals 一致。
3条答案
按热度按时间pbgvytdp1#
这实际上已经相当支持了,使用Assert语法。
$x_1a^0b^1x$
sgtfey8w2#
Assert方法只能缩小,对吧?你不能用它们来扩大或修改类型。所以任何具有
obj.prop
状态的类型在调用obj.turnPropIntoANumber()
之后开始时是string
,但结束时是number
,这不是我们可以在 TS 中建模的东西。oug3syen3#
我认为最小的改变就是允许将Assert和函数/方法的返回类型组合在一起,例如 "(Assert this 是 AnotherType) & 返回类型"。