TypeScript与Vue #

一、Vue组件类型 #

1.1 defineComponent #

typescript
import { defineComponent } from 'vue';

export default defineComponent({
    name: 'UserCard',
    props: {
        name: {
            type: String,
            required: true
        },
        age: {
            type: Number,
            default: 0
        }
    },
    setup(props) {
        return {
            greeting: `Hello, ${props.name}!`
        };
    }
});

1.2 script setup #

typescript
<script setup lang="ts">
import { ref, computed } from 'vue';

interface Props {
    name: string;
    age?: number;
}

const props = defineProps<Props>();

const greeting = computed(() => `Hello, ${props.name}!`);
</script>

二、Props类型 #

2.1 基本Props #

typescript
interface Props {
    title: string;
    count?: number;
    items: string[];
}

const props = defineProps<Props>();

2.2 带默认值的Props #

typescript
interface Props {
    title: string;
    count?: number;
}

const props = withDefaults(defineProps<Props>(), {
    count: 0
});

2.3 复杂Props #

typescript
interface User {
    id: number;
    name: string;
}

interface Props {
    user: User;
    onUpdate: (user: User) => void;
}

const props = defineProps<Props>();

三、Emits类型 #

3.1 定义Emits #

typescript
interface Emits {
    (e: 'update', value: string): void;
    (e: 'delete', id: number): void;
}

const emit = defineEmits<Emits>();

emit('update', 'new value');
emit('delete', 1);

3.2 script setup #

typescript
<script setup lang="ts">
const emit = defineEmits<{
    (e: 'update', value: string): void;
    (e: 'delete', id: number): void;
}>();
</script>

四、响应式类型 #

4.1 ref #

typescript
import { ref } from 'vue';

const count = ref<number>(0);
const name = ref<string>('');
const user = ref<User | null>(null);

4.2 reactive #

typescript
import { reactive } from 'vue';

interface State {
    count: number;
    name: string;
    items: string[];
}

const state = reactive<State>({
    count: 0,
    name: '',
    items: []
});

4.3 computed #

typescript
import { computed } from 'vue';

const doubleCount = computed<number>(() => count.value * 2);

const fullName = computed<string>(() => {
    return `${firstName.value} ${lastName.value}`;
});

五、Composition API #

5.1 基本用法 #

typescript
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue';

interface User {
    id: number;
    name: string;
}

const users = ref<User[]>([]);
const loading = ref(false);

const fetchUsers = async () => {
    loading.value = true;
    const response = await fetch('/api/users');
    users.value = await response.json();
    loading.value = false;
};

onMounted(fetchUsers);
</script>

5.2 自定义组合函数 #

typescript
import { ref, Ref } from 'vue';

function useFetch<T>(url: string): {
    data: Ref<T | null>;
    loading: Ref<boolean>;
    error: Ref<Error | null>;
    fetch: () => Promise<void>;
} {
    const data = ref<T | null>(null);
    const loading = ref(false);
    const error = ref<Error | null>(null);
    
    const fetch = async () => {
        loading.value = true;
        try {
            const response = await fetch(url);
            data.value = await response.json();
        } catch (e) {
            error.value = e as Error;
        } finally {
            loading.value = false;
        }
    };
    
    return { data, loading, error, fetch };
}

六、模板引用 #

6.1 ref引用 #

typescript
<script setup lang="ts">
import { ref } from 'vue';

const inputRef = ref<HTMLInputElement | null>(null);

const focus = () => {
    inputRef.value?.focus();
};
</script>

<template>
    <input ref="inputRef" />
    <button @click="focus">Focus</button>
</template>

6.2 组件引用 #

typescript
<script setup lang="ts">
import ChildComponent from './ChildComponent.vue';

const childRef = ref<InstanceType<typeof ChildComponent> | null>(null);
</script>

七、实用示例 #

7.1 表单组件 #

typescript
<script setup lang="ts">
import { reactive } from 'vue';

interface FormData {
    username: string;
    password: string;
}

const form = reactive<FormData>({
    username: '',
    password: ''
});

const emit = defineEmits<{
    (e: 'submit', data: FormData): void;
}>();

const handleSubmit = () => {
    emit('submit', { ...form });
};
</script>

7.2 列表组件 #

typescript
<script setup lang="ts">
interface User {
    id: number;
    name: string;
}

interface Props {
    users: User[];
}

defineProps<Props>();

const emit = defineEmits<{
    (e: 'select', user: User): void;
}>();
</script>

<template>
    <ul>
        <li v-for="user in users" :key="user.id" @click="emit('select', user)">
            {{ user.name }}
        </li>
    </ul>
</template>

八、总结 #

本章介绍了TypeScript与Vue的结合:

组件类型 #

  1. defineComponent
  2. script setup
  3. Props类型

响应式类型 #

  1. ref
  2. reactive
  3. computed

最佳实践 #

  1. 使用script setup
  2. 显式定义Props和Emits类型
  3. 使用组合函数复用逻辑
最后更新:2026-03-26