'`as const` alternative to narrow an array literal tuple, to avoid `readonly` modifiers
We use as const
to narrow the types:
[ {foo: 'foo' }, { bar: 'bar' } ] as const
but this also adds readonly
modifiers for all props and values. As of const
this makes sens, but I would like to have the narrowing, without the readonly
modifiers, as offen you want to modify the objects in tuple, or just pass it further to some method, which is of the same interface, but without deep readonly
let foo = [ {foo: 'foo' }, { bar: 'bar' } ]
here the foo is of type:
({
foo: string;
bar?: undefined;
} | {
bar: string;
foo?: undefined;
})[]
but I would expect to get
[{
foo: string;
}, {
bar: string;
}]
There for we use as const
, but in most cases it is not possible, as foo
/bar
get deeply nested readonly
modifiers, we could use something like
type DeepWritable<T> = { -readonly [P in keyof T]: DeepWritable<T[P]> };
But it would be wired to use as const
which adds readonly
, and then DeepWritable
to remove it.
Do you know any alternative to as const
to narrow the tuple type without having manually to define types.
Solution 1:[1]
You can use the following generic function to constrain the type as a tuple:
const Tuple = <T extends [any, ...any]>(v:T) => v
And then wrap the literal:
let foo = Tuple([ {foo: 'foo' }, { bar: 'bar' } ]) // foo: [{ foo: string }, { bar: string }]
Solution 2:[2]
Here is a better generic Tuple
function, since it preserves tuple member literal values too:
export type Writable<T> = {
-readonly [K in keyof T]: T[K];
};
export const Tuple = <T extends readonly [unknown, ...unknown[]]>(v: T) =>
v as Writable<T>;
Use it like so:
const foo = Tuple([{foo: 'foo' }, { bar: 'bar' }] as const)
// foo: [{ readonly foo: 'foo' }, { readonly bar: 'bar' }]
// Note the array itself is not readonly, only the object properties are
See the relevant TypeScript 3.4 release note for reference.
Also worth checking out this related, more thorough answer
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | ccarton |
Solution 2 |