如何在TypeScript中模拟标称类型?

如何在TypeScript中模拟标称类型?,typescript,casting,type-conversion,Typescript,Casting,Type Conversion,我在我的项目中有许多函数,它们以数字作为参数;这个数字有一半时间是数组的索引,另一半时间是光标位置(数组中两个条目之间的点)。这会导致混淆,即使使用命名约定也是如此 我想强调的是,下面的函数采用了预期的标称类型 class Index extends Number {} class CursorPosition extends Number {} function getElement(i: Index) {} function getRange(p1: CursorPosition, p2:

我在我的项目中有许多函数,它们以数字作为参数;这个数字有一半时间是数组的索引,另一半时间是光标位置(数组中两个条目之间的点)。这会导致混淆,即使使用命名约定也是如此

我想强调的是,下面的函数采用了预期的标称类型

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
我知道typescript使用结构类型,这就是为什么它不会“开箱即用”的原因

此外,我还考虑了装箱变量和添加任意属性:

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);
class myNum{
arb:“任意属性值”;
}
常数mn2:myNum=8;
函数getElement2(a:any[],i:myNum){
返回一个[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 
您需要定义一个helper函数来创建该类型的实例,或者使用类型断言(
constmyindex=1,如任何as Index
),但是如果您传递一个简单的数字,调用站点将给出错误


这是一个关于这个话题的讨论。此外,typescript编译器使用此方法处理

您可以使用品牌类型:

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 
您需要定义一个helper函数来创建该类型的实例,或者使用类型断言(
constmyindex=1,如任何as Index
),但是如果您传递一个简单的数字,调用站点将给出错误


这是一个关于这个话题的讨论。typescript编译器也使用这种方法来进行

typescript在其路线图的“未来”部分中具有标称类型@B没错,这张票已经飘了一段时间了,我们来看看会有什么结果:)我已经用过这个q几次了,对结果很满意。通常,您可以使用标称类型代替基本类型,但不能使用相反的方式(不强制转换)。TypeScript在其路线图的“未来”部分具有标称类型@B没错,这张票已经飘了一段时间了,我们来看看会有什么结果:)我已经用过这个q几次了,对结果很满意。通常,您可以使用公称类型代替基本类型,但不能使用其他方式(无铸造)。