typescript中的GUID/UUID类型

typescript中的GUID/UUID类型,types,typescript,guid,uuid,Types,Typescript,Guid,Uuid,我有这个功能: function getProduct(id: string){ //return some product } 其中id实际上是GUID。Typescript没有guid类型。是否可以手动创建类型GUID function getProduct(id: GUID){ //return some product } 因此,如果“xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxx”将是一些“notGuidbutJustSt

我有这个功能:

function getProduct(id: string){    
    //return some product 
}
其中id实际上是GUID。Typescript没有guid类型。是否可以手动创建类型
GUID

function getProduct(id: GUID){    
    //return some product 
}
因此,如果“xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxx”将是一些“notGuidbutJustString”,那么我将看到类型脚本编译错误


更新:正如David Sherret所说:无法确保在编译时基于正则表达式或其他函数的字符串值,但可以在运行时在一个位置执行所有检查。

您可以围绕字符串创建一个包装器,并传递:

class GUID {
    private str: string;

    constructor(str?: string) {
        this.str = str || GUID.getNewGUIDString();
    }

    toString() {
        return this.str;
    }

    private static getNewGUIDString() {
        // your favourite guid generation function could go here
        // ex: http://stackoverflow.com/a/8809472/188246
        let d = new Date().getTime();
        if (window.performance && typeof window.performance.now === "function") {
            d += performance.now(); //use high-precision timer if available
        }
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
            let r = (d + Math.random() * 16) % 16 | 0;
            d = Math.floor(d/16);
            return (c=='x' ? r : (r & 0x3 | 0x8)).toString(16);
        });
    }
}

function getProduct(id: GUID) {    
    alert(id); // alerts "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
}

const guid = new GUID("xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx");
getProduct(guid); // ok
getProduct("notGuidbutJustString"); // errors, good

const guid2 = new GUID();
console.log(guid2.toString()); // some guid string
更新

另一种方法是使用品牌:

type Guid = string & { _guidBrand: undefined };

function makeGuid(text: string): Guid {
  // todo: add some validation and normalization here
  return text as Guid;
}

const someValue = "someString";
const myGuid = makeGuid("ef3c1860-5ce6-47af-a13d-1ed72f65b641");

expectsGuid(someValue); // error, good
expectsGuid(myGuid); // ok, good

function expectsGuid(guid: Guid) {
}

我认为我们应该对大卫·谢雷特的回答作一点扩展
像这样:

// export 
class InvalidUuidError extends Error {
    constructor(m?: string) {
        super(m || "Error: invalid UUID !");

        // Set the prototype explicitly.
        Object.setPrototypeOf(this, InvalidUuidError.prototype);
    }

}


// export 
class UUID 
{
    protected m_str: string;

    constructor(str?: string) {
        this.m_str = str || UUID.newUuid().toString();

        let reg:RegExp = new RegExp("[A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12}", "i")
        if(!reg.test(this.m_str))
            throw new InvalidUuidError();
    }

    toString() {
        return this.m_str;
    }

    public static newUuid(version?:number) :UUID
    {
        version = version || 4;


        // your favourite guid generation function could go here
        // ex: http://stackoverflow.com/a/8809472/188246
        let d = new Date().getTime();
        if (window.performance && typeof window.performance.now === "function") {
            d += performance.now(); //use high-precision timer if available
        }
        let uuid:string = ('xxxxxxxx-xxxx-' + version.toString().substr(0,1) + 'xxx-yxxx-xxxxxxxxxxxx').replace(/[xy]/g, (c) => {
            let r = (d + Math.random() * 16) % 16 | 0;
            d = Math.floor(d/16);
            return (c=='x' ? r : (r & 0x3 | 0x8)).toString(16);
        });

        return new UUID(uuid);
    }
}


function getProduct(id: UUID) {    
    alert(id); // alerts "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
}


const guid2 = new UUID();
console.log(guid2.toString()); // some guid string


const guid = new UUID("xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx");
getProduct(guid); // ok
getProduct("notGuidbutJustString"); // errors, good

如果能够基于正则表达式在TypeScript中定义类型,那就太好了。我知道在TypeScript 4.1之后有字符串文字类型,但我真的希望能够定义一个类型
UUID
,例如使用下面这样的正则表达式

export type UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i; 

这是可以预见的吗?

但是这个包装器将我的问题转移到了其他地方,因为我仍然可以做到:const guid=new guid(“notGuidbutJustString”)。当然,我可以在GUID类中添加一些运行时检查,但我希望在应用程序启动之前看到错误…@Rajab无法确保编译时基于regex或其他函数的字符串值。我建议使用书面的单元测试来解决这个问题,这很遗憾。也许这在将来会改变,但无论如何,你的答案是有帮助的。谢谢我已经创建了一个关于包含单元测试的小类型脚本。相关问题在。可能的副本可以使用类型别名,但它不会提供任何编译时检查。只是给开发者一个提示<代码>类型Guid=字符串我很好奇您编写完整UUID的频率,这是必需的,这只会在编译时验证,对吗?抱歉,我只是没有看到用例。我们不编写UUID,但有时希望能够识别它们,例如,当我们的一个微服务与包含非结构化数据的数据库或其他服务对话时。