javascript 如何在TypeScript中实现具有一组值的接口?

eyh26e7m  于 2023-01-01  发布在  Java
关注(0)|答案(2)|浏览(115)

我尝试在类中实现一个接口,如下所示:

type TLanguage = "TYPE" | "SCRIPT" // Reusable values

interface AnyInterface {
    business: TLanguage
    /** MoreTypes */
}

class Anyclass implements AnyInterface{
    business = "TYPE"
}

这会抛出一个错误:
类型"Anyclass"中的属性"business"不能赋给基类型"AnyInterface"中的同一属性。类型"string"不能赋给类型"TLanguage"。ts(2416)
预期的行为是,每当我在TLanguage作用域之外设置任何business值时,它都会抛出一个错误......当我在变量中设置它时,它确实工作:

const anyConst: AnyInterface = {
    business: "TYPE" //✅
    business: "TYPEs" //❌ Type '"TYPEs"' is not assignable to type 'TLanguage'. Did you mean '"TYPE"'?ts(2820)
}
6ojccjat

6ojccjat1#

当一个类implements一个接口时,它实际上并不影响类的类型。编译器 * 检查 * 该类是否与接口兼容,但它并不使用接口作为 * 上下文 * 来为类的成员给予类型。这是TypeScript的一个痛点。因为人们确实期望发生某种上下文推断。有关详细信息,请参阅microsoft/TypeScript#32082和其中链接的问题。
当你写class Anyclass implements AnyInterface {...}时,编译器的行为和你写class Anyclass {...}而不写implements AnyInterface的行为非常相似。如果你不正确地实现它(或者如果编译器推断出这一点),你会在Anyclass名称上得到一个错误。
因此,问题是class Anyclass { business = "TYPE" }会导致business从字面类型"TYPE"自动扩展到string,因为编译器没有上下文来做其他事情,而implements AnyInterface不会改变这一点。
这也意味着这里的解决方案与省略implements AnyInterface后的解决方案相同,可以显式地“注解”字段的类型:

class Anyclass implements AnyInterface {
    business: TLanguage = "TYPE"
}

或者你可以使用一个constAssert来请求编译器不要加宽字符串文字(但是这将推断"TYPE"而不是TLanguage作为属性类型):

class Anyclass implements AnyInterface {
    business = "TYPE" as const
    // (property) Anyclass2.business: "TYPE"
}

或者你可以把它变成一个readonly属性,它也提示编译器不要加宽(所以它是"TYPE"),并且也不允许你重新分配它:

class Anyclass implements AnyInterface {
    readonly business = "TYPE"
    // (property) Anyclass3.business: "TYPE"
}

Playground代码链接

q8l4jmvw

q8l4jmvw2#

您可以使用as const修复此问题:

type TLanguage = "TYPE" | "SCRIPT" 

interface AnyInterface {
    business: TLanguage
    /** MoreTypes */
}

class Anyclass implements AnyInterface{
    business = "TYPE" as const
}

相关问题