mobily/ts-belt

A qustion about ReadOnly

Closed this issue · 3 comments

Thanks for your work on this awesome library
I'm trying to replace lodash with this in my project, but not sure whether i'm using this library in a idiomatic way

sometimes components only accept mutable types, is it a right practice that manually converting result to un-readonly type by using as keyword?
for example

export declare type PickerColumnItem = {
    label: ReactNode;
    value: string;
};
export declare type PickerColumn = (string | PickerColumnItem)[];
export declare type PickerViewProps = {
    columns: PickerColumn[] | ((value: PickerValue[]) => PickerColumn[]);
}

when i pass a A.map output to the columns prop, tsc complaint that:

The type 'readonly { value: string; label: string; }[]' is 'readonly' and cannot be assigned to the mutable type 'PickerColumn'.

and fix this by as PickerColumnItem[]

This causing me lot of issues too, consider this example:

const obj = {foo: 1, bar: 2}
const myKeys = ['foo', 'bar'] as const;

D.selectKeys(obj, myKeys);

and this produce same error as mentioned The type 'readonly ["foo", "bar"]' is 'readonly' and cannot be assigned to the mutable type '("foo" | "bar")[]'

I really like this library but this is causing my lot of problems. Is really necessary for type to be mutable? I think it should work without any issue for readonly since lib will never mutate passed params.

Thanks.

// edit:
One of possible workaround for these that are affected by this could be this:

type Writeable<T> = { -readonly [P in keyof T]-?: T[P] };

D.selectKeys(obj, myKeys as Writeable<typeof obj>);

@leviathan-n ts-belt is using immutable arrays by default and frankly speaking, this is a common problem, I have added a possibility for using either immutable or mutable arrays

to use mutable arrays in the entire project, simply add the following in your global.d.ts:

declare namespace Belt {
  type UseMutableArrays = 1
}

although you may still want to use immutable arrays (which is a recommended approach), then starting from v3.11.0 you can use the F.toMutable helper instead of the as keyword:

const xs = pipe(
  items,
  A.map(),
  F.toMutable,
) // → PickerColumnItem[]

links:
https://mobily.github.io/ts-belt/docs/getting-started/config#immutable-vs-mutable
https://mobily.github.io/ts-belt/api/function#tomutable

@Nodonisko your case is different, D.selectKeys and D.deleteKeys had broken signatures, and it's been fixed in v3.11.0 as well 🚀 I have added a simple test to cover this case:

expectType<typeof rec>(D.selectKeys(rec, keys))

@mobily Wow, thank you a lot! That significantly improves my DX :)