#reverse const assertion / remove readonly from variables
38 messages · Page 1 of 1 (latest)
A writable array cannot be type ["a", "b"], because it can be updated, changing it's contents
The type of a variable isn't it's current value, but its acceptable values
also arr2 refers to the same array as arr, so if you update arr2 it will update arr, breaking the readonly restriction
Preview:ts const arr = ["a", "b"] as const // ^? const arr2 = [...arr] // ^?
You can do this
const arr = ["a", "b"] as const; // readonly ["a", "b"]
const arr2 = [...arr] // ("a" |"b")[]
@vague fiber
Thanks @cloud cedar , my usage is actually not to modify the the second array, and is mostly to satisfy other condition (something like a function that accept ("a" | "b")[] but wont accept a readonly array), I'll try to destruct to a new array instead
oh just cast it
func(arr as ("a" | "b")[])
Technically the other function should declare that it takes readonly arrays, which guarantees that it does not modify it
But if you are certain that it only reads, and just has not been typed correctly, then you can cast
you can probably also redeclare the type of the func somehow
Preview:```ts
function foo(arr: ("a" | "b")[]) {}
const tuple = ["a", "b"] as const
foo(tuple as unknown as ("a" | "b")[])
type RealFoo = (arr: readonly ("a" | "b")[]) => void
;(foo as RealFoo)(tuple)```
Here are 2 options
Thanks @cloud cedar ! I will probably use the second one, I don't like using as unknown as usually, feels a but like cheating or like using any
!solved
it's not as unknown really, its just a hack so typescript will let us cast to ("a" | "b")[]
tuple as unknown as ("a" | "b")[] is tuple as ("a" | "b")[]
casting to unknown isn't* really dangerous anyway, as it says we know nothing and will usually throw up a lot of errors. Casting to any is the total opposite of that, as it just disables checking
But yeah i think the second one is better
Preview:```ts
import {foo as _foo} from "foo"
type RealFoo = (arr: readonly ("a" | "b")[]) => void
const foo = _foo as RealFoo
const tuple = ["a", "b"] as const
foo(tuple)```
here's a cleaner way
You can take it further to the point of point the RealFoo stuff in a module, so you just import from your own cleanup module
import { foo } from './clean-foo.js'
Obviously if you can contacat the auther and give them to fix the types that is even better : )
this is inaccurate
being a tuple and being readonly are separate things
the cast from unknown is dangerous though.
it is effectively a non-infectious as any
Right
so the compiler was highlighting my error, can just do
foo(tuple as ['a', 'b'])
Now I'm curious. Mapping a type preserves the readonly status, which suggests that readonly is a property of the entries not the object
type WritableTuple<X extends readonly [...unknown[]]> = {
[K in keyof X]: X[K]
}
type W = WritableTuple<readonly ['a', 'b']>
type W2 = WritableTuple<['a', 'b']>
Preview:```ts
type WritableTuple<X extends readonly [...unknown[]]> =
{
-readonly [K in keyof X]: X[K]
}
type W = WritableTuple<readonly ["a", "b"]>```
@vague fiber Here you go. Here's the solution to what you asked, thanks to some prompting by @solid storm : )
Yes that is the solution, would love in the future for typescript to have -readonly or -? on non objects
?