打字稿字符串或自定义类型

时间:2021-06-02 11:08:23

标签: javascript typescript typescript-typings

我有以下几点:

type gio = {
    metadata: any;
}


let a:gio | string;

问题:键入 a.metadata 会产生错误 Property 'metadata' does not exist on type 'string | gio'.

3 个答案:

答案 0 :(得分:3)

试试这个:

type gio = {
    metadata: any;
}


let a: gio | string;

if(typeof a !== 'string'){
    a.metadata
}

答案 1 :(得分:1)

| 将获取包含在这两种类型中的所有属性 - 因此它的类型将是 giostring 之间的公共属性。由于 string 没有 metadata 属性,因此不会包含在最终类型中。你需要的是&

type gio = {
    metadata: any;
}

let a:gio & string;

这样 gio 和 string 的属性将被组合在一起,您将能够访问 a.matadata

答案 2 :(得分:1)

编辑:snaksa's answer 使用 intersection types 会起作用,但区别在于 let a: gio & string 意味着任何值 a 设置为必须是有效的 gio 还有一个有效的字符串,这意味着它必须具有元数据字段以及字符串的所有成员(length、indexOf()、trim()等) . 这类似于写 interface MyNewType implements gio, string


From the docs:

<块引用>

TypeScript 只允许你使用联合做一些事情,如果联合的每个成员都有效。

例如,如果 gio 被定义为:

type gio = {
    metadata: any;
    length: number;
}

您可以访问 a.length,因为 giostring 都有一个长度字段。
另一方面,您不能访问 a.metadata,因为 a 可能是 string,也不能访问 a.indexOf(),因为它可能是 gio

<块引用>

解决办法是用代码缩小联合...
例如,TypeScript 知道只有一个字符串值才会有一个 typeof 值“string”:

所以,as Dor ben Itzhak answered

if(typeof a !== 'string') { 
   // a is not a string, therefore it is gio
    a.metadata
} else { 
   // a is a string
   a.indexOf("foo")
}

或者如果你想告诉 ts“相信我,这是一个 gio”,你可以使用 type assertion

(a as gio).metadata

为了记录,There's a whole section in the docs for more complicated narrowing