您如何在TypeScript中模拟名义键入? [英] How do you emulate nominal typing in TypeScript?
问题描述
我的项目中有很多函数,这些函数都以数字作为参数。此数字的一半时间是数组的索引,另一半时间是光标位置(数组中两个条目之间的点)。即使使用命名约定,这也会引起混乱。
I have many functions in my project that take an number as parameter; half the time this number is an index into an array, the other half of the time, it is a cursor position (a point between two entries in an array). This causes confusion, even with naming conventions.
我要强制以下功能采用预期的名义类型。
I would like to enforce that the functions below are taking the intended nominal types.
class Index extends Number {}
class CursorPosition extends Number {}
function getElement(i: Index) {}
function getRange(p1: CursorPosition, p2: CursorPosition) {}
const myIndex: Index = 6;
const myPosition: CursorPosition = 6;
getElement(1); // would like this to fail at compile time
getRange(2, 3); // would like this to fail at compile time
getElement(myPosition); // would like this to fail at compile time
getRange(myIndex, myIndex); // would like this to fail at compile time
getElement(myIndex); // would like this to pass at compile time
getRange(myPosition, myPosition); // would like this to pass at compile time
我知道打字稿使用结构化打字,这是为什么没有开箱即用呢?
I understand that typescript uses structural typing, and this is why this does no occur "out of the box".
此外,我也考虑过将变量装箱并添加仲裁属性:
Also, I have considered both boxing my variables and adding a arbitray propery:
class myNum extends Number {
l: "1";
}
或使用强制转换。
class myNum {
arb: "arbitrary property value";
}
const mn2: myNum = <any>8;
function getElement2(a: any[], i: myNum) {
return a[<any>i];
}
getElement2([], mn2);
getElement2([], 6);
还有更好的主意吗?
推荐答案
您可以使用品牌类型:
type Index = Number & { __type: 'Index'}
type CursorPosition = Number & { __type: 'CursorPosition'}
function getElement(i: Index) {}
function getRange(p1: CursorPosition, p2: CursorPosition) {}
function indexFromNumber(n: number) :Index {
return n as any;
}
function cursorPositionFromNumber(n: number): CursorPosition {
return n as any;
}
const myIndex: Index = indexFromNumber(6);
const myPosition: CursorPosition = cursorPositionFromNumber(6);
getElement(1); // error
getRange(2, 3); // error
getElement(myPosition); // error
getRange(myIndex, myIndex); // error
getElement(myIndex); // ok
getRange(myPosition, myPosition); //ok
您需要定义一个辅助函数来创建类型实例或使用类型断言( const myIndex = 1等于索引
),但是如果您传递一个简单的数字,则呼叫站点将给出错误。
You need to define a helper function to create instances of the type or use type assertions ( const myIndex = 1 as any as Index
), but the call site will give errors if you pass a simple number.
此文章还有更多内容关于该主题的讨论。打字稿编译器还将这种方法用于路径
This article has a bit more of a discussion on the topic. Also the typescript compiler uses this approach for paths
这篇关于您如何在TypeScript中模拟名义键入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!