#javascript #typescript #vue.js
#javascript #машинописный текст #vue.js
Вопрос:
С помощью Vue composition API мы создали следующий составной:
import { computed, reactive, SetupContext, ref } from '@vue/composition-api'
export const useApplications = (root: SetupContext['root']) => {
const applications = reactive({
1: {
name: ref(root.$t('app1.name')),
description: ref(root.$t('app1.description')),
formName: 'app1form',
},
2: {
name: ref(root.$t('app2.name')),
description: ref(root.$t('app2.description')),
formName: 'app2form',
},
})
const getApplication = (id: string) => {
return applications[id]
}
return {
applications: computed(() => applications),
getApplication,
}
}
Хотя код работает нормально, он генерирует ошибку TS:
@typescript-eslint/no-unsafe-return: небезопасный возврат любого введенного значения
При наведении курсора мыши на applications
раздел становится ясно, что typescript распознает типы, за исключением имени свойства ( 1
):
Нужно ли нам создавать интерфейс для решения этой проблемы и нужно ли переопределять каждое свойство в интерфейсе? Я пробовал что-то подобное, но это неверно:
interface IApplication {
[key]: string {
name : string
description: string
formName: string
}
}
Комментарии:
1. Из любопытства, зачем использовать объект с цифровыми клавишами, а не массив?
2. Для ограничений с массивами в composition API в Vue 2
3. Я буду верить, что это ответ, если вы знаете задействованные библиотеки. В противном случае, похоже, это ничего не объясняет.
4. Сначала я использовал an
array
. Но есть проблемы с этим подходом для системы реактивности Vue в Vue 2. В любом случае спасибо за помощь, очень признателен.
Ответ №1:
TypeScript обычно не вводит данные, поэтому они могут быть проиндексированы любым строковым ключом. Как вы говорите, вы можете определить для него интерфейс:
interface IApplications {
[key: string]: {
name : string;
description: string;
formName: string;
};
}
// ...
const applications: IApplications = ...
Или вы можете просто использовать тип для части объекта и использовать встроенный Record
тип для applications
:
interface IApplication {
name : string;
description: string;
formName: string;
}
// ...
const applications: Record<string, IApplication> = ...
Или объединение этих двух:
interface IApplication {
name : string;
description: string;
formName: string;
}
type IApplications = Record<string, IApplication>;
(Или вы можете встроить IApplication
часть. Или… 🙂 )
Комментарии:
1. Спасибо, это было именно то, что я искал. Я просто надеялся, что мне не придется переопределять свойства
name
,description
иformName
поскольку они уже известны TS с помощью автоматической интерпретации. Но, похоже, нам нужно создать полный объект.2. @DarkLite1 — Да, было бы неплохо, если бы он мог вывести эту часть. Может быть, это возможно (так много), я просто не сразу вижу это. 🙂
Ответ №2:
В соответствии со структурой параметров reactive
функции, интерфейс может быть определен как :
interface IApplication {
[key:string]:{
name : string
description: string
formName: string
}
}
и
const applications = reactive<IApplication>({ ...
Но я хочу предложить другой подход, который определяет tha applications
как reactive
параметр, который имеет массив в качестве значения:
import { computed, reactive, SetupContext, ref ,toRef} from '@vue/composition-api'
interface IApplication {
name : string
description: string
formName: string
}
export const useApplications = (root: SetupContext['root']) => {
const state= reactive<Array<IApplication>>({ applications :
[{
name: ref(root.$t('app1.name')),
description: ref(root.$t('app1.description')),
formName: 'app1form',
},
{
name: ref(root.$t('app2.name')),
description: ref(root.$t('app2.description')),
formName: 'app2form',
}],
})
const getApplication = (index: number) => {
return state.applications[index]
}
return {
applications: toRef(state,'applications'),
getApplication,
}
}