#How do I assign an index signature to an object literal while keeping the inferred type?

13 messages · Page 1 of 1 (latest)

south pierBOT
#
balam314#0

Preview:```ts
let data = {
a: 1,
b: 2,
c: 3,
d: 4,
e: 5,
f: 6,
g: 7,
}
let data2: Record<string, number> = {
a: 1,
b: 2,
c: 3,
d: 4,
e: 5,
f: 6,
g: 7,
}

let str = "" as string

if (data[str]) {
}
if (data2[str]) {
}
let _: keyof typeof data
// ^?
let __: keyof typeof data2
...```

radiant basin
#

how do I add an index signature without losing the autocomplete for the keys?

#

is there anything better than ```ts
(<T>(d:T) => d as T & {[index:string]: number | undefined;})({
...
})

brisk hinge
#

There's not really a nice way to do it, but what are you trying to achieve?

#

It's not really common to want what you are asking for.

radiant basin
#

I want to be able to do if (data[str]) { and also get autocomplete on data

#

its possible

south pierBOT
#
balam314#0

Preview:```ts
declare const x: {
[index: string]: string | undefined
foo: "bar"
}

x.foo
//^?
x.amogus
//^?
if (x["blah"]) {
}```

brisk hinge
#

I mean yes it's possible but it also forces you to cast.

#

It's basically a case of

#

!:known*

south pierBOT
#
retsam19#0
`!retsam19:known-and-unknown-keys`:

TS doesn't work well with objects that mix "known keys" of one type onto an object with unknown keys (i.e. an index signature) for a different type.

type DoesNotCompile = {
    [key: string]: number; // all unknown keys are numbers
    specificKey: string; // but this key is a string
}

You can 'fake' it with intersections:

type Compiles = { [key: string]: number;}
  & { specificKey: string };

but this type is essentially read-only. You can read from it as you'd expect, but you can't assign anything to this type (without an assertion).

If your API isn't set in stone, it's recommended to put the unknown keys in their own object:

type Idiomatic ={
   specificKey: string;
   unknownKeys: Record<string, number>;
}
brisk hinge
#

The only difference is that the first snippet will compile, but the read only point still stands.