0

Why does using a mapped generic type result in it being equal to string instead of an Object ?


// doesn't work
type getActions<T> = { [N in keyof T]: T[N] };

// works
type getActions2 = { [N in keyof ""]: ""[N] };

// { at: (a: 1) => 'false' } not assignable to string
const oef: getActions<string> = { at: (a: 1) => 'false' }; 

TS Playground

Twiggeh
  • 1,030
  • 1
  • 12
  • 24
  • What makes you think this should work? `getActions` is basically a copy machine, so you're trying to do something like `const oef: string = somethingNotAString` here basically – kelsny Mar 21 '22 at 15:31
  • Are you trying to get all actions that result in type `T`? – kelsny Mar 21 '22 at 15:31

1 Answers1

0

This is just TS working as intended, there is very little use-case where the default behavior of iterating over a String's prototypical keys are actually what someone wants to do, hence why this doesn't work. More often than not this type of accessing the keys of string Object is used in intersections to "brand" a string, rather than actually access it's prototype methods

type test = getActions<string & {brand: 'Brand'}> extends {brand: 'Brand'} ? true : false
//  ^? `type test = true`

Looks like you are trying to type the experimental .at

You'll have to jump through some hoops but here is where I sourced my answer from: How to extend String Prototype and use it next, in Typescript?

Extending the modules in this way can only be done in a special declaration > .d.ts files*.

//in a .d.ts file:
declare global {
    interface String {
        at(a: number) : string;
    }
}

This assumes you implement or polyfill the at yourself. Otherwise you'll have to change the library tsconfig option to es2022 or later to support .at

Cody Duong
  • 2,292
  • 4
  • 18