在接口中定义时,字符串文字类型的字段分配错误

Posted

技术标签:

【中文标题】在接口中定义时,字符串文字类型的字段分配错误【英文标题】:String literal typed field assign error when defined in interface 【发布时间】:2019-02-23 07:02:42 【问题描述】:

当在接口中定义字符串字面量类型时,我得到了意想不到的行为。

interface IFoo 
    value: 'foo' | 'boo';

当我在类中实现接口时出现错误:

class Foo implements IFoo 
    value = 'foo';

我收到一个错误:“Foo”类型中的属性“值”不能分配给基类型“IFoo”中的相同属性。但 'foo' 是字符串文字的正确值。

另一方面:

class Boo implements IFoo 
    value;
    constructor() 
        this.value = 'foo';
        this.value = 'boo';
        this.value = 'koo'; // must be an error Boo doesn't implement IFoo
    

const test = new Boo();
test.value = 'koo';

此代码不会导致任何错误,但Boo.value 属于any 类型。我预计会收到 Boo 未实现 IFoo 的错误,但没有任何错误。

我发现唯一正确的方法是这样实现类:

class Koo implements IFoo 
    value: 'foo' | 'boo' = 'foo';

所以我不得不声明枚举:

enum Doos  foo = 'foo', boo = 'boo' 
interface IDoo 
    value: Doos;

class Doo implements IDoo 
    value = Doos.foo;

const test = new Doo();
test.value = Doos.boo;

我理解这是因为 ts 编译器从字段声明中的分配值中获取了 Doo.value 类型。看起来在接口中声明字符串文字类型的字段没有用,或者我做错了什么。并且还发现类可以实现任何字段类型的接口,所以这取决于开发人员。

【问题讨论】:

【参考方案1】:

问题是您希望implements IFoo 影响类字段的键入方式。它不是。事情发生的方式是,类字段的类型就像implements Foo 不存在一样,并且在完全解析类类型之后,检查与实现的接口的兼容性。这样看,错误是有道理的。

class Foo implements IFoo 
    value = 'foo'; // this is typed as string, not as the string literal type and thus is not compatible with value in IFoo 

class Boo implements IFoo 
    // no type, no init, value is typed as any and any is compatible with 'foo' | 'boo' 
    // use -noImplicitAny to avoid such errors
    value; 
    constructor() 
        this.value = 'foo';
        this.value = 'boo';
        this.value = 'koo'; // 'koo' is compatible with any
    

当您使用枚举时,一切正常,因为如果我们将枚举的值分配给字段,该字段将被键入为枚举。

您可以指定value 字段的类型,显式或相对于IFoo 接口:

class Foo implements IFoo 
    value: IFoo['value'] = 'foo';

或者如果字段是readonly,它将被键入为字符串文字类型:

class Foo implements IFoo 
    readonly value = 'foo';

【讨论】:

以上是关于在接口中定义时,字符串文字类型的字段分配错误的主要内容,如果未能解决你的问题,请参考以下文章

golang 自定义接口体(与其他语言对象类似)

如何使用 Enum 类型的字段执行 Typesafe JSON?

java sql SQLException ORA-01861 文字和格式字符串不匹配

为啥允许将字符串文字分配给 C++ 中 char * 类型的指针 [重复]

在 C# 中将字符串文字分配给字符串

错误函数()。字符串未定义(类型字符串没有字段或方法字符串)