有没有办法在打字稿中定义一个新的(而不是别名)类型?

时间:2016-06-06 12:48:38

标签: types typescript

如果我定义以下类型:

type seconds = number;
type milliseconds = number;

类型只是别名,以下语法不会引发任何错误:

var x:seconds = 1;
var y:milliseconds = x;

虽然我希望打字稿可以防止在没有演员的情况下进行这样的作业。有没有办法创造新的名义类型?

注意:我发现this proposal,不确定自那以后是否有新的发布。

4 个答案:

答案 0 :(得分:0)

这只是一种解决方法,我担心(在Playground中查看)

interface Seconds {
    'These are seconds': string
    value: number
}

interface MilliSeconds {
    'These are milliseconds': string
    value: number
}

const s = <Seconds>{ value: 3}
const ms = <MilliSeconds>{ value: 3}

let wrong: Seconds = ms // <= compilation error

答案 1 :(得分:0)

  

有没有办法创造新的名义类型

您必须从根本上打破结构兼容性。你在布鲁诺的回答中看到过一种方式。另一个是使用枚举:

// FOO
enum FooIdBrand {}
type FooId = FooIdBrand & string;

// BAR
enum BarIdBrand {}
type BarId = BarIdBrand & string;

/**
 * Usage Demo
 */
var fooId: FooId;
var barId: BarId;

// Safety!
fooId = barId; // error
barId = fooId; // error

// Newing up
fooId = 'foo' as FooId;
barId = 'bar' as BarId;

// Both types are compatible with the base
var str: string;
str = fooId;
str = barId;

这里涵盖了两种方式https://basarat.gitbooks.io/typescript/content/docs/tips/nominalTyping.html

答案 2 :(得分:0)

我的答案可能是对@basarat的回答更好的评论,但这对评论来说太过分了,所以无论如何我都会把它留在这里,因为你可能觉得它很方便。

此处还有另一个名义类型的相关提案:https://github.com/Microsoft/TypeScript/issues/202

在那次讨论中,Ryan Cavanaugh has suggested using Branded types大致得到了你想要的东西:

// Once
type Branded<T, U> = T & { '__ kind': U };

// Elsewhere
type OrderID = Branded<string, 'Order ID'>;

@ basarat的伎俩很相似,但我无法使用它来处理数字。

所以在你的情况下,它将是:

type Branded<T, U> = T & { '__ kind': U };

type Milliseconds = Branded<number, 'Milliseconds'>;
type Seconds = Branded<number, 'Seconds'>;

let secondsValue: Seconds = <Seconds>5;
let millisecondsValue: Milliseconds = <Milliseconds>5;

secondsValue = millisecondsValue; // Error, just as you want

secondsValue = <Seconds>(secondsValue + secondsValue); // Works
secondsValue = secondsValue + secondsValue; // Doesn't work :(
secondsValue = <Seconds>(secondsValue + millisecondsValue); // Also works :(

Playground link 所以,它并不完美,但你至少必须故意为彼此分配任意数字,这比使用类型别名更好。

答案 3 :(得分:0)

自2016年以来,仍然没有对此的本地支持,但是软件包uom-ts试图模拟这种行为。 https://github.com/mindbrave/uom-ts是他们的示例:

import { Unit } from "uom-ts";

type Kg = Unit<{kg: 1}>;
type Pounds = Unit<{lb: 1}>;

const mass: Kg = 1.0 as Kg; // ok

const mass2: Kg = 1.0 as Pounds; // error
const mass3: Kg = 1.0; // error