由于可以使用VueJSv-bind: style
绑定设置CSS变量,我试图创建一个联合类型,其中传递给v-bind: style
的对象保留了CssStyleDelcaration
的类型,但足够轻松接受任意属性名称:
type Dictionary<T> = { [key: string]: T };
type Nullable<T> = T | null;
type CssStyleObject =
Partial<CSSStyleDeclaration> |
Dictionary<Nullable<string>>;
实现的一个例子是这样的(请参阅TypeScript playground上的实时代码):
<!-- Template -->
<div v-bind:style="myStyle"></div>
// Component code
@Component
export default class MyComponent extends Vue {
public get myStyle(): CssStyleObject {
const style: CssStyleObject = { };
style.backgroundColor = 'red';
style['--my-custom-css-property'] = '16px';
}
}
但是,当我启用了noInInimplatiany
标志(由于项目范围的配置,我无法关闭该标志)时,我会出现类型错误,因为TypeScript会抱怨:
元素隐式具有“any”类型,因为类型“CssStyleObject”没有索引签名。
我在这里看到了一个建议的解决方案:当编译类型脚本时,如果没有启用任何标志,我如何防止错误对象类型的索引签名隐含地具有'any'类型?,但是如果有另一个,我很想避免简单地转换为any
可行的解决方案是可能的。
有趣的是,在分配给样式
变量时,一旦使用自定义属性名,错误消息就会消失:
const style: CssStyleObject = {
'--foobar': '50%'
};
style.backgroundColor = 'red';
style['--my-custom-css-property'] = '16px';
请参阅上面TypeScript Playground上的代码。
我怀疑这是因为类型为样式
然后以某种方式修改为简单的字典
所以,事实证明我天生就混淆了TypeScript中的交集和并集类型。在这种情况下,CssStyleObject
是Partial的交点
type Dictionary<T> = { [key: string]: T };
type Nullable<T> = T | null;
// Use `&` for creating an intersection type!
type CssStyleObject =
Partial<CSSStyleDeclaration> &
Dictionary<Nullable<string>>;
首先,您的代码的当前行为是因为区分的联合类型的工作方式。CSSStyle声明
没有索引签名,而字典有。因此,当您在声明中添加自定义属性时,该类型被推断为字典
。
其次,如果要向现有类型添加索引,则不应使用联合类型。您应该改用交叉点类型。也就是说,CssStyleObject
是一个CSSStyleDeclaration
并具有索引签名,但不是一个CssStyleObject
或具有索引签名的对象
最后,这里是工作代码
type CssStyleObject = Partial<CSSStyleDeclaration> & Record<string, string | null>
// or
interface CssStyleObject extends Partial<CSSStyleDeclaration> {
[key: string]: string | null
}