#allowing type hints for parameter object properties

36 messages · Page 1 of 1 (latest)

rotund stratus
#

I'm not sure if this has been done somewhere. I don't know what to search either. this is a really niche thing that I don't think is practical but give it a try

#
type Tr<T extends readonly Fn[]> = {
  [K in keyof T]: T[K] extends (p: infer P) => infer R
    ? (p: Record<keyof P, string>) => R
    : never;
};

function c<T extends readonly Fn[]>(fns: Tr<T>) {
  return fns;
}

const ls = c([
  //
  ({ name }) => `Hola ${name}`,
  // ^?
  // should be type hinted as string
  ({ age }) => `The age ${age}`,
]);

vital violetBOT
#
0xc0c0a#0

Preview:```ts
type Tr<T extends readonly Fn[]> = {
[K in keyof T]: T[K] extends (p: infer P) => infer R
? (p: Record<keyof P, string>) => R
: never
}

function c<T extends readonly Fn[]>(fns: Tr<T>) {
return fns
}

const ls = c([
//
({name}) => `Hola ${name
...```

rotund stratus
#

@reef tulip

reef tulip
#

do you use nouncheckedindexedaccess?

glass stream
#

What about simply?

type Fn = (arg: Record<string, string>) => string

function c(fns: Fn[]) {}
#

It would work without nUIA, which you don't have it turned on in the playground.

rotund stratus
reef tulip
#

the easiest solution would be to just use the big-ball-of-overloads approach that pipe uses

glass stream
#

How would that work?

#

From my understanding, name and age are arbitrary strings so it needs to work with anything.

#

I don't think it's possible to do for arbitrary strings, since destructuring is implementation and does not affect types, so it's not possible to extract them.

#

You would have to change the API and repeat name/age somewhere in the types.

reef tulip
#

hmmm

#

yeah i guess

rotund stratus
#

idk it kinda relates to #1214295571037290556
i think they have noUncheckedIndexedAccess off but i was personally curious about this

vital violetBOT
reef tulip
#

!ts

vital violetBOT
#
function c<K extends string>(fn: (arg: Record<K, string>) => string) {
  return [fn];
}

const ls = c(
//         ^? - function c<string>(fn: (arg: Record<string, string>) => string): ((arg: Record<string, string>) => string)[]
  ({ name }) => `Hola ${name}`,
//   ^? - (parameter) name: string
);```
reef tulip
#

so probably a classic inference order issue

#

to get the param names the lambda needs to have started inference

glass stream
#

I'm pretty sure { name } just doesn't participate in inference what so ever.

reef tulip
#

the function either infers before the lambdas start, or after the lambdas finish

rotund stratus
#

that is what im also curious about. it does have the signature any

reef tulip
#

either way you cannot go from the lambdas to the outer function and back

rotund stratus
glass stream
#

It makes sense for destructuring to be handled like:

({ name }) => {}

// same as

(_arg) => {
    const { name } = _arg
}

So if that's the case, it's simply impossible to extract name at all.

rotund stratus
#

!ts

vital violetBOT
#
const j = ({ name }) => `${name}`
//           ^^^^
// Binding element 'name' implicitly has an 'any' type.
//    ^? - const j: ({ name }: {
//        name: any;
//    }) => string
rotund stratus
#

@glass stream the hint makes it look like _arg is inferred to be { name: any; }

#

so maybe i thought there was a way to get the keys

glass stream
#

Hmm that does seem to be the case.

vital violetBOT
#
nonspicyburrito#0

Preview:ts type Validate<T> = T extends never ? T : { [K in keyof T]: T[K] extends (arg: infer A) => string // ? (arg: Record<keyof A, string>) => string ? [(arg: Record<keyof A, string>) => string] : never } ...

glass stream
#

Toggle commenting/uncommenting L5 and L6

#

It seems like TS can infer that, but it breaks once you try to use L5.