I have a small problem that I've been unable to solve after several hours. I don't know if a sharper mind could offer me a solution?
this is xxx
.But unfortunately, i can't seem to find a solution to allow this approach. Maybe a lacking from typescript !?
Everything work as i want, but this thing drive me crazy :) ! If anyone has any ideas ho to remove this last error in my code ? see: 🔴
I've simplified the example to the minimum
thanks a lot
type RemoveSuper<A extends number[]> = { // remove number constructor in tuple [number,1,2] => [1,2]
[K in keyof A]: number extends A[K] ? never : A[K]
}
type EntityWith<N extends number[] > = { //entity with numbers (branding)
has< T extends N >( componentType: T ):boolean
}
type ExtractGenericInIntersection<T> = (
T extends Entity<infer C> ? ( c:C[number]) => void : never
) extends ( r: infer R2 ) => void ? [R2[]] : never
type Entities<T extends Entity> = ExtractGenericInIntersection<T> extends [infer R extends number[]]
? EntityWith<R> | Entity<R>
: never
export interface Entity<C extends number[] = number[]> {
has: <T extends RemoveSuper<C>[number]>( componentType: T ) => this is Entity<[T]>;
}
type A = Entity<[1]>
type B = Entity<[1, 2]>
declare const entities: Entities<A|B>;
//@ts-expect-error
entities.has( 2 );
entities.has( 1 );//🔴
The problem was related to a limitation of type
that do not handle this
.
Interfaces
seem to support this
, which allows branding works.
By replacing type with interface the branding work.
type EntityWith<
C extends Component,
R extends ComponentType = never,
E extends Entity = Entity,
> = E & {
has<T extends R>(componentType: T): boolean
}
by
interface EntityWith<
C extends Component,
R extends ComponentType = never,
> extends Entity {
has< T extends R>( componentType: T ): this is Entity<InstanceType<T>, []>
}
Now it reflet correcly the method in class
abstract class Entity {
declare has: <T extends RemoveSuper<M>>(componentType: T) => this is Entity<InstanceType<T>, []>
}