我尝试在类中实现一个接口,如下所示:
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)
}
2条答案
按热度按时间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
后的解决方案相同,可以显式地“注解”字段的类型:或者你可以使用一个
const
Assert来请求编译器不要加宽字符串文字(但是这将推断"TYPE"
而不是TLanguage
作为属性类型):或者你可以把它变成一个
readonly
属性,它也提示编译器不要加宽(所以它是"TYPE"
),并且也不允许你重新分配它:Playground代码链接
q8l4jmvw2#
您可以使用
as const
修复此问题: