К сожалению, тайпскрипт так до сих пор делать не научился. В некоторых случаях могло бы помочь satisfies
, но тут и оно не прикручивается.
Поэтому делаем по-старинке: сначала объявляем переменную с as const
, а потом проверяем, что получившийся тип соответствует всем желаемым огранияениям.
Playground:
interface IQuestion<A extends readonly [string, string, string, string] = readonly [string, string, string, string]> {
readonly title: string;
readonly answers: A;
readonly answer: A[number];
readonly description: string;
}
const questions = [{
title: "What is the most common job in the world?",
answers: ["Doctor", "Farmer", "Teacher", "Cook"],
answer: "Farmer",
description: ""
}, {
title: "Title",
answers: ["Test 1", "Test 2", "Test 3", "Test 4"],
answer: "Farmer",
description: ""
}] as const;
type QuestionsAreIQuestionArray = typeof questions extends readonly IQuestion[]
? {}
: "questions should be IQuestion[]"
type NumericKeysFor<T extends readonly any[], A extends any[] = [], R = never> = A["length"] extends T["length"] ? R : NumericKeysFor<T, [...A, any], R | A["length"]>
type EachQuestionHasValidAnswer = {
[key in NumericKeysFor<typeof questions>]: (typeof questions)[key] extends { readonly answers: readonly [infer A, infer B, infer C, infer D], readonly answer: infer R } ? R extends A | B | C | D ? {} : `Question ${key} has invalid answer` : `Question ${key} is invalid`;
}[NumericKeysFor<typeof questions>];
interface _CheckQuestions extends QuestionsAreIQuestionArray, EachQuestionHasValidAnswer {}
Ошибка несоответствия типов проявит себя на строке с неиспользуемым интерфейсом _CheckQuestions
- хотя он больше и не используется, он либо скомпилируется, либо нет. В приведённом примере получится ошибка:
