Использовал «Equals» для проверки на равенство
type Equals<A1, A2> = (<A>() => A extends A2 ? 1 : 0) extends (<A>() => A extends A1 ? 1 : 0) ? 1 : 0;
но есть проблема
interface User {
id: string;
name?: string;
}
type test0 = Equals<User, { id: string; name?: string }>;
// test0 => 1 expect ok
type test1 = { id: string; name?: string } extends Record<string, unknown> ? 1 : 0;
// test1 => 1 expect ok
type test2 = User extends Record<string, any> ? 1 : 0;
// test2 => 1 expect ok
type test3 = User extends object ? 1 : 0;
// test3 => 1 expect ok
type test4 = User extends Record<string, unknown> ? 1 : 0;
// test4 => 0 I can't understand why?
если "Пользователь" является псевдонимом
type User1 = {
id: string;
name?: string;
};
type test5 = User1 extends Record<string, unknown> ? 1 : 0;
// test1 => 1 Unbelievable why?
Почему «test4» и «test5» ведут себя так? Что я сделал не так? Какие правила к этому приводят? Является ли тип «равно» неправильным?
Причина в том, что интерфейсы могут быть объединены, поэтому их свойства выводятся.
См. здесь: https://github.com/microsoft/TypeScript/issues/42825, который описывает точно такую же проблему, как вы описываете здесь.
https://github.com/microsoft/TypeScript/issues/42825#issuecomment-789242594 является подходящим объяснением
Why is IFoo not assignable to
Record<PropertyKey, unknown>
then? What am I missing?This is exactly the train of thought that lead to anything being assignable to
Record<string, any>
, but there was concern from users at the time that then there was no way to indicate that they only wanted to accept things with a declared index signature. This makes a lot of sense if you intend to write to the received object, since if you alias anIFoo
by aRecord<string, unknown>
then you can trivially corrupt it through e.g.myAlias["type"] = 0