你如何模拟 TypeScript 中的名义输入? [英] How do you emulate nominal typing in TypeScript?

查看:13
本文介绍了你如何模拟 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 as any as Index),但是如果您传递一个简单的号.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆