I have the following code, which works in TypeScript 3.0.1 but gives compile errors in 3.1.3. If possible, I'd like to know what changed in 3.1.+ that makes the code invalid, or if this may be a compiler bug.
export interface Entity {
id: number | string;
}
export type IdOf<E extends Entity> = E['id'];
export interface EntityState<E extends Entity> {
ids: IdOf<E>[];
entities: { [key: string]: E, [key: number]: E };
}
export function getAllEntities<E extends Entity>(state: EntityState<E>): E[] {
const { ids, entities } = state;
return ids.map(id => entities[id]);
}
export function getEntity<E extends Entity>(id: IdOf<E>, state: EntityState<E>): E | undefined {
const { ids, entities } = state;
if (!ids.includes(id)) {
return undefined;
}
return entities[id];
}
As I said, it compiles fine in 3.0.1, but in 3.1.3 I get the following errors:
BUILD ERROR
projects/entity/src/lib/entity-state.utils.ts(13,5): error TS2322: Type '{ [key: string]: E; [key: number]: E; }[E["id"]][]' is not assignable to type 'E[]'.
Type '{ [key: string]: E; [key: number]: E; }[E["id"]]' is not assignable to type 'E'.
Type 'Entity' is not assignable to type 'E'.
projects/entity/src/lib/entity-state.utils.ts(23,5): error TS2322: Type '{ [key: string]: E; [key: number]: E; }[E["id"]]' is not assignable to type 'E | undefined'.
Type 'Entity' is not assignable to type 'E'.
Type '{ [key: string]: E; [key: number]: E; }[E["id"]]' is not assignable to type 'E'.
Type 'Entity' is not assignable to type 'E'.
The two errors correspond to the two functions' return statements, respectively.
Edit. For completeness, I'll just mention that I intend for users to create subinterfaces of Entity and EntityState for their domain types, overriding id to be a more restrictive type. This is why the IdOf type is important. E.g.,
interface Task extends Entity {
id: string;
due: Date;
title: string;
}
interface TaskState extends EntityState<Task> {
// Inherits EntityState#ids as string[]
currentTask?: string;
}