Я нашел обходной путь, но на самом деле решение не идеальное:
interface MyType {
id: string;
value: number;
}
const myType: MyType = {
id: '',
value: 0
};
type ArrType<T> = Array<keyof T>;
function isMyTypeArr<T>(arg: any[]): arg is ArrType<T> {
return arg.length === Object.keys(myType).length;
}
function checkKeys<T>(arr: ArrType<T>): void {
if (isMyTypeArr(arr)) {
console.log(arr.length);
// some other stuff
}
}
checkKeys<MyType>(['id', 'x']); // TS error
checkKeys<MyType>(['id']); // no console because of Type Guard
checkKeys<MyType>(['id', 'value']); // SUCCESS: console logs '2'
Идея состоит в том, чтобы создать простой объект, который реализует исходный интерфейс.Нам нужен этот объект, чтобы получить длину ключей для сравнения в isMyTypeArr
Type Guard.Тип Guard просто сравните длину массивов - если они имеют одинаковую длину, это означает, что вы предоставляете все свойства.
Edit
Добавлен еще один аналог (более общее) решение - основные отличия:
- использование класса с параметрами конструктора, который реализует исходный интерфейс;
- у этого класса есть свойство
length
(потому что в основном это функция конструктора), мы можем использовать его в нашем Type Guard; - мы также должны передать имя класса в качестве второго параметра, чтобыполучить его конструктор аргументов длины.Мы не можем использовать универсальный тип
T
для этого, потому что скомпилированный JS имеет всю информацию о типе, мы не можем использовать T
для нашей цели, проверить этот пост для более подробной информации
Итак, это окончательное решение:
interface IMyType {
id: string;
value: number;
}
class MyType implements IMyType {
constructor(public id: string = '', public value: number = 0) {}
}
type ArrType<T> = Array<keyof T>;
function isMyTypeArr<T>(arg: ArrType<T>, TClass: new () => T): arg is ArrType<T> {
return arg.length === TClass.length;
}
function checkKeys<T>(arr: ArrType<T>, TClass: new () => T): void {
if (isMyTypeArr<T>(arr, TClass)) {
console.log(arr.length);
// some other stuff
}
}
checkKeys<MyType>(['id', 'x'], MyType); // TS error
checkKeys<MyType>(['id'], MyType); // no console because of Type Guard
checkKeys<MyType>(['id', 'value'], MyType); // SUCCESS: console logs '2'
Обратите внимание, что эти примеры основаны на Проблемы с TypeScript 13267
пстакже создал демонстрацию stackblitz обоих примеров