如何在打字稿中创建不同的数字类型?

时间:2017-11-25 12:10:38

标签: typescript

我想定义不同的数字类型,这样我就不会意外地混淆它们,如下所示:

let h = 0 as Height;
let w = 0 as Width;

// These shall panic
h === w;
h + w;

// These shall work
(h as number) === (w as number);
(h as number) + (w as number);

类型别名不起作用,因为它们仅为方便起见,并且被视为相同的类型:

// This definition works but does not enforce type checking over just
// using 'number'
type Height = number;
type Width = number;

关于如何解决这个问题的任何想法?

修改:添加了(h + w)也将失败的要求

2 个答案:

答案 0 :(得分:0)

将类型分配为不同数字类型的唯一方法是模拟接口并为接口分配唯一字段。

interface IHeight { height: any }
interface IWidth { width: any }

declare type Width = number & IWidth;
declare type Height = number & IHeight;

let h = 0 as Height;
let w = 0 as Width;

现在你不能直接h = w而不再将其再次编号。

答案 1 :(得分:0)

对于您的情况,这可能有点过分,但我使用类来防止意外等效,例如使用实体ID。我还使用类来封装单元 - 这样既可以实现类型安全,也可以让您拥有单元转换的逻辑主页。

class Width {
  constructor(private value: number) { }

  get pixels() {
    return this.value;
  }
}

class Height {
  constructor(private value: number) { }

  get pixels() {
    return this.value;
  }
}

这假定您使用标准单位创建尺寸。您可以添加其他属性访问器,以便以不同的单位(如CM,英寸等)返回高度。

当您使用WidthHeight时,它们不兼容,因此您无法将它们混淆:

function getArea(width: Width, height: Height) {
  return width.pixels * height.pixels;
}

// number not assignable to `Width`
getArea(3, 4);

// `Height` is not assignable to `Width`
getArea(new Height(2), new Width(4));

// `Width` is not assignable to `Height`
getArea(new Width(2), new Width(4));

// Ok
getArea(new Width(2), new Height(4));

在大多数情况下,您可以将其用于端到端类型的安全性(就像您动态创建new Width(5)一样......也就是说{{1}是宽度 - 所以你试图阻止的错误仍会蔓延。)因此,在大多数情况下,您可以从返回5Width的内容中获取值,这会阻止经典的... Height数字意外传递为高度

obj.Heigl