Skip to content

Type of intersection of two object types A and B is not equal to A & B #25

@wvanderdeijl

Description

@wvanderdeijl

I am trying to build a generic type with @skunkteam/types that takes an existing (object) type and extends it with a number of fields (id in this example):

import { BaseObjectLikeTypeImpl, intersection, object, string, The, TypeImpl } from '@skunkteam/types';

export type ObjectType<ResultType> = TypeImpl<BaseObjectLikeTypeImpl<ResultType>>;

export type Person = The<typeof Person>;
export const Person = object('Person', { name: string });

export type RestDocument<T> = T & { id: string };
export function RestDocument<T>(type: ObjectType<T>): ObjectType<RestDocument<T>> {
    return intersection(`RestDocument<${type.name}>`, [object({ id: string }), type]);
}

Unfortunately this throws a typescript error:

error TS2322: Type 'TypeImpl<IntersectionType<[TypeImpl<InterfaceType<{ id: TypeImpl<BaseTypeImpl<string>>; }, TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>>>, TypeImpl<...>]>>' is not assignable to type 'TypeImpl<BaseObjectLikeTypeImpl<RestDocument<T>>>'.
  Type 'TypeImpl<IntersectionType<[TypeImpl<InterfaceType<{ id: TypeImpl<BaseTypeImpl<string>>; }, TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>>>, TypeImpl<...>]>>' is not assignable to type 'BaseObjectLikeTypeImpl<RestDocument<T>>'.
    The types returned by 'and(...)' are incompatible between these types.
      Type 'TypeImpl<IntersectionType<[TypeImpl<IntersectionType<[TypeImpl<InterfaceType<{ id: TypeImpl<BaseTypeImpl<string>>; }, TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>>>, TypeImpl<...>]>>, any]>>' is not assignable to type 'TypeImpl<IntersectionType<[BaseObjectLikeTypeImpl<RestDocument<T>>, any]>>'.
        Type 'TypeImpl<IntersectionType<[TypeImpl<IntersectionType<[TypeImpl<InterfaceType<{ id: TypeImpl<BaseTypeImpl<string>>; }, TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>>>, TypeImpl<...>]>>, any]>>' is not assignable to type 'IntersectionType<[BaseObjectLikeTypeImpl<RestDocument<T>>, any]>'.
          Types of property 'types' are incompatible.
            Type '[TypeImpl<IntersectionType<[TypeImpl<InterfaceType<{ id: TypeImpl<BaseTypeImpl<string>>; }, TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>>>, TypeImpl<...>]>>, any]' is not assignable to type '[BaseObjectLikeTypeImpl<RestDocument<T>>, any]'.
              Type 'TypeImpl<IntersectionType<[TypeImpl<InterfaceType<{ id: TypeImpl<BaseTypeImpl<string>>; }, TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>>>, TypeImpl<...>]>>' is not assignable to type 'BaseObjectLikeTypeImpl<RestDocument<T>>'.
                The types returned by 'and(...)' are incompatible between these types.
                  Type 'TypeImpl<IntersectionType<[TypeImpl<IntersectionType<[TypeImpl<InterfaceType<{ id: TypeImpl<BaseTypeImpl<string>>; }, TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>>>, TypeImpl<...>]>>, any]>>' is not assignable to type 'TypeImpl<IntersectionType<[BaseObjectLikeTypeImpl<RestDocument<T>>, any]>>'.
                    Type 'TypeImpl<IntersectionType<[TypeImpl<IntersectionType<[TypeImpl<InterfaceType<{ id: TypeImpl<BaseTypeImpl<string>>; }, TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>>>, TypeImpl<...>]>>, any]>>' is not assignable to type 'IntersectionType<[BaseObjectLikeTypeImpl<RestDocument<T>>, any]>'.
                      Types of property 'types' are incompatible.
                        Type '[TypeImpl<IntersectionType<[TypeImpl<InterfaceType<{ id: TypeImpl<BaseTypeImpl<string>>; }, TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>>>, TypeImpl<...>]>>, any]' is not assignable to type '[BaseObjectLikeTypeImpl<RestDocument<T>>, any]'.
                          Type 'TypeImpl<IntersectionType<[TypeImpl<InterfaceType<{ id: TypeImpl<BaseTypeImpl<string>>; }, TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>>>, TypeImpl<...>]>>' is not assignable to type 'BaseObjectLikeTypeImpl<RestDocument<T>>'.
                            The types returned by 'typeValidator(...)' are incompatible between these types.
                              Type 'Result<MergeIntersection<T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>>>' is not assignable to type 'Result<RestDocument<T>>'.
                                Type 'Success<MergeIntersection<T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>>>' is not assignable to type 'Result<RestDocument<T>>'.
                                  Type 'Success<MergeIntersection<T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>>>' is not assignable to type 'Success<RestDocument<T>>'.
                                    Type 'MergeIntersection<T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>>' is not assignable to type 'RestDocument<T>'.
                                      Type '(T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>) | { [P in keyof (T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)]: MergeIntersection<...>; }' is not assignable to type 'RestDocument<T>'.
                                        Type '{ [P in keyof (T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)]: MergeIntersection<(T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)[P]>; }' is not assignable to type 'RestDocument<T>'.
                                          Type '{ [P in keyof (T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)]: MergeIntersection<(T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)[P]>; }' is not assignable to type 'T'.
                                            'T' could be instantiated with an arbitrary type which could be unrelated to '{ [P in keyof (T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)]: MergeIntersection<(T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)[P]>; }'.
                                              Type 'MergeIntersection<(T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)[P]>' is not assignable to type 'T[P]'.
                                                Type '{ id: string; }' is not assignable to type 'RestDocument<T>'.
                                                  Type '{ id: string; }' is not assignable to type 'T'.
                                                    'T' could be instantiated with an arbitrary type which could be unrelated to '{ id: string; }'.
                                                      Type 'MergeIntersection<T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>>' is not assignable to type 'T'.
                                                        'T' could be instantiated with an arbitrary type which could be unrelated to 'MergeIntersection<T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>>'.
                                                          Type '(T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>) | { [P in keyof (T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)]: MergeIntersection<...>; }' is not assignable to type 'T'.
                                                            'T' could be instantiated with an arbitrary type which could be unrelated to '(T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>) | { [P in keyof (T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)]: MergeIntersection<...>; }'.
                                                              Type '{ [P in keyof (T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)]: MergeIntersection<(T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)[P]>; }' is not assignable to type 'T'.
                                                                'T' could be instantiated with an arbitrary type which could be unrelated to '{ [P in keyof (T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)]: MergeIntersection<(T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)[P]>; }'.
                                                                  Type 'MergeIntersection<(T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)[P]>' is not assignable to type 'T[P]'.
                                                                    Type '(T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)[P] | { [P in keyof (T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)[P]]: MergeIntersection<...>; }' is not assignable to type 'T[P]'.
                                                                      Type '{ [P in keyof (T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)[P]]: MergeIntersection<(T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)[P][P]>; }' is not assignable to type 'T[P]'.
                                                                        Type 'MergeIntersection<(T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)["id" | keyof T]>' is not assignable to type 'T[P]'.
                                                                          Type '(T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)["id" | keyof T] | { [P in keyof (T & TypeOfProperties<Writable<{ id: TypeImpl<...>; }>>)["id" | keyof T]]: MergeIntersection<...>; }' is not assignable to type 'T[P]'.
                                                                            Type '(T["id"] & string) | (T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)[keyof T]' is not assignable to type 'T[P]'.
                                                                              Type 'T["id"] & string' is not assignable to type 'T[P]'.
                                                                                Type 'MergeIntersection<T["id"] & string> | MergeIntersection<(T & TypeOfProperties<Writable<{ id: TypeImpl<BaseTypeImpl<string>>; }>>)[keyof T]>' is not assignable to type 'T[P]'.
                                                                                  Type 'MergeIntersection<T["id"] & string>' is not assignable to type 'T[P]'.
                                                                                    Type '(T["id"] & string) | { [P in keyof (Record<string | number | symbol, unknown> & T["id"] & string)]: MergeIntersection<(Record<string | number | symbol, unknown> & T["id"] & string)[P]>; }' is not assignable to type 'T[P]'.
                                                                                      Type 'T["id"] & string' is not assignable to type 'T[P]'.
                                                                                        Type 'string' is not assignable to type 'T[P]'.
                                                                                          Type '{ id: string; }' is not assignable to type 'T'.
                                                                                            'T' could be instantiated with an arbitrary type which could be unrelated to '{ id: string; }'.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions