Appearance
指令使用过程中 ts 约束值的类型
当我们在使用指令的时候,往往需要传递一些值,那么这些值该如何约束呢?
举个例子
vue
<template>
<div>
<div v-my-direct="{ type: 'apple' }"></div>
</div>
</template>
<script lang="ts" setup>
import { defineDirective } from "vue";
const vMyDirect = defineDirective({
mounted(el, binding) {
console.log(binding.value); // { type: 'apple'}
},
});
</script>在上面的例子中,我们在指令中使用了 binding.value 来获取传递的值,但是这个值的类型是 any,如果我们想要约束这个值只能是apple、banana、orange中的一个,否则编译时会报错,已达到类型约束的目的。
解决方法
这里不赘述一些其他的方法,直接给出通用的解决办法
新建指令文件
ts
// src/directives/my-direct.ts
import { DirectiveBinding } from "vue";
// binding请给具体的类型,方便在mounted里面使用
export const myDirect = {
mounted(el: HTMLElement, binding: DirectiveBinding) {
console.log(binding.value);
},
};全局注册指令
ts
// src/main.ts
import { createApp } from "vue";
import App from "./App.vue";
import { myDirect } from "./directives/my-direct";
const app = createApp(App);
app.directive("my-direct", myDirect);
app.mount("#app");新建类型文件
注意
这里我们要全局去扩展 vue 的类型
ts
// src/types/directives.ts
import type { Directive } from "vue";
type MyDirectType = "apple" | "banana" | "orange";
declare module "vue" {
interface ComponentCustomProperties {
vMyDirect: Directive<Element, { type: MyDirectType }>;
}
}修改 tsconfig.json
json
{
"compilerOptions": {
"strict": true, // 严格模式 注意这里开启后,ts会进行严格的类型检查,意味着你必须要去处理一些类型,如any
"typeRoots": ["./node_modules/@types", "./src/types"]
}
}使用指令
vue
<template>
<div>
<!-- 正确 -->
<div v-my-direct="{ type: 'apple' }"></div>
<!-- 错误 -->
<div v-my-direct="{ type: 'pear' }"></div>
</div>
</template>所有代码
vue
<template>
<div>
<div v-my-direct="{ type: 'apple' }"></div>
</div>
</template>ts
import type { Directive } from "vue";
export type MyDirectType = "apple" | "banana" | "orange";
declare module "vue" {
interface ComponentCustomProperties {
vMyDirect: Directive<Element, { type: MyDirectType }>;
}
}ts
import { DirectiveBinding } from "vue";
import type { MyDirectType } from "../types/directives";
export const myDirect = {
mounted(el: HTMLElement, binding: DirectiveBinding<{ type: MyDirectType }>) {
console.log(binding.value.type); // 类型是MyDirectType,而且开发工具会有相关提示
},
};ts
import { createApp } from "vue";
import App from "./App.vue";
import { myDirect } from "./directives/my-direct";
const app = createApp(App);
app.directive("my-direct", myDirect);
app.mount("#app");json
{
"compilerOptions": {
"strict": true, // 严格模式 注意这里开启后,ts会进行严格的类型检查,意味着你必须要去处理一些类型,如any
"typeRoots": ["./node_modules/@types", "./src/types"]
}
}