TypeScript中的严格类型别名

6
我希望定义一种类型来表示API接收到的ISO日期时间字符串。我想要保证虽然该表示是字符串,但不能分配给任何字符串。编译器应该捕获这些赋值,以便我可以在适用时进行转换。因此,我想在golang中实现类似于type Time string的东西。
以下TS代码是允许的,我需要防止这种分配:const time: Time = "..."
type Time = string; 
const message: string = 'hello world';
const time: Time = message;

TypeScript Playground

编辑1:

通过下面提到的Json文章,我可以增加安全性,防止任意字符串传递到Time类型,但反过来是可能的。 在const someType: number = fourthOfJuly;处不会出现错误。

enum DateStrBrand { }
export type DateStr = string & DateStrBrand;

const fourthOfJuly = toDateStr('2017-07-04');
const someType: string = fourthOfJuly;


function checkValidDateStr(str: string): str is DateStr {
  return str.match(/^\d{4}-\d{2}-\d{2}$/) !== null;
}

export function toDateStr(date: string): DateStr {
  if (typeof date === 'string') {
    if (checkValidDateStr(date)) {
      return date;
    } else {
      throw new Error(`Invalid date string: ${date}`);
    }
  }
  throw new Error(`Shouldn't get here (invalid toDateStr provided): ${date}`);
}

TypeScript Playground


“在 const someType: string = fourthOfJuly; 没有错误。” 这是个问题吗?DateStr 应该是 string 的子类型,因此可以将 DateStr 值分配给 string 变量,但反之则不行。这里还有什么需要回答的吗? - jcalz
由于正则表达式验证的字符串类型不是该语言的一部分,因此在编译时支持你所做的事情没有更好的选择。 - jcalz
@jcalz 谢谢确认。我进行了编辑以显示没有将错误分配给数字或任何类型。这有点糟糕 :-) const someType: number = fourthOfJuly; - bsr
啊,自从TS3.6以来,空的“enum”标识已经失效了。因此,也许可以使用一个带有私有成员的类,例如“class DateStrBrand { private dateStrBrand =“DateStr” }”。 - jcalz
请从此处获取有关编程的相关内容。 - jcalz
谢谢。我刚刚通过搜索“枚举品牌”找到了那个页面。我不知道这是一件事 :-) 我会试试的。 - bsr
2个回答

1
基于 @jcalz 上面的评论,结合以下资源,我总结出了下面的内容。

https://basarat.gitbook.io/typescript/main-1/nominaltyping

export interface DateStr extends String {
  ____dateStrBrand: string; // To prevent type errors
}

// Safety!
var fooId: Time = "..."; // error
fooId = "..." as any; // OK

// If you need the base string
var str: string;
str = fooId; // error
str = fooId as any; // OK

0

谢谢Jason。这是个不错的技巧。让我们看看是否有更好的方法在编译时检测所有错误。 - bsr
2
请注意,自TS3.6以来,空的“enum”标记已经无法使用;相反,我可能会使用一个带有私有成员的类,例如class DateStrBrand { private dateStrBrand = "DateStr" } - jcalz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接