Description
π Search Terms
destructure omit
π Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about
- 3.x
- 4.x
- 5.x
β― Playground Link
-
Updated link. A simplified version, with the resulting type as an example.
https://www.typescriptlang.org/play?#code/CYUwxgNghgTiAEAzArgOzAFwJYHtXwHMQMBJYAHgFkdQIAaeMgPgAoBbGkCALnmtoCUvMgG4AUGJTpseeHA4A3EACVwOGBTHw+nCPBAAPDCFTAAzvBwAjAFbgMdLY2D6jJ8-ADkiHDk-wAHy8rWE8xVjMMKGN+LjNeVTB1CjIGWIgmBg5aXnSheETk8lSdWiZ4AG8nJNRI+CwXAF5CYjIqXQZmdl0BcWq8Oor4AG0GgF1eWmIQYABRVGwMAE8GADp17Lj4AF94ZsjokHSzPu04DGQYfE2IE7FtvqwFkBhEKDAEWbYAB2XCjUq2wkUkwuHw8hwSn+wAA6uoANZPAjkJzpVzGUwWax2TCObRkdHuCzeXz+IKeEIwMIRKIxXTxApqDTFYBpXSZeA3XI9XhfX5LaGVfq1DD1JotUgUdKdYCsG69CTaGqDEbjSZcaZzBZYZZrDb0nZ7eAHOm0O5Oc6Xa708QPIA
π» Code
Updated example:
declare function getId<Model, Id>(model: Model): Id;
function removeRecord<
Model extends object,
Id extends 'foo' | 'bar'
>(stateModels: Record<Id, Model>, model: Model): Record<Id, Model> {
const id = getId<Model, Id>(model);
const { [id]: deletedEntity, ...models } = stateModels;
return models;
};
Original Example:
type ModelKey = string | number;
type ModelsWithId<Model, Key extends ModelKey> = Record<Key, Model>;
declare function getIdWithKey<Model, Key>(model: Model): Key;
function removeRecordWithKey<
Model extends object,
Key extends ModelKey
>(stateModels: ModelsWithId<Model, Key>, model: Model): ModelsWithId<Model, Key> {
const id = getIdWithKey<Model, Key>(model);
const { [id]: deletedEntity, ...models } = stateModels;
return models;
};
π Actual behavior
And error is thrown in the return statement:
Type 'Omit<ModelsWithId<Model, Key>, Key>' is not assignable to type 'ModelsWithId<Model, Key>'.
Type 'Key' is not assignable to type 'Exclude<Key, Key>'.
Type 'ModelKey' is not assignable to type 'never'.
Type 'string' is not assignable to type 'never'.(2322)
The result type is an empty object
interface EmptyRecord {}
function removeRecordWorking<
Model extends object,
Id extends 'foo' | 'bar'
>(stateModels: Record<Id, Model>, model: Model): EmptyRecord {
const id = getId<Model, Id>(model);
const { [id]: deletedEntity, ...models } = stateModels;
return models; // No errors
};
π Expected behavior
No error should be thrown, because an object with a removed keyed property, should be equal to the same object.
Additional information about the issue
When you don't use a keyed property, the code is valid:
interface RemoveModel {
id: string;
}
type ModelWithStringKey = Record<string, RemoveModel>;
function remove(state: ModelWithStringKey, model: RemoveModel): ModelWithStringKey {
const id = model.id;
const { [id]: deletedEntity, ...models } = state;
return models;
};
The Playground link for "Original example" has different examples for more complex and simpler scenarios.