#Inferring a type parameter taking an array of keys of O

22 messages · Page 1 of 1 (latest)

sinful bone
#

ChatGPT failed to figure this out in maybe 16 attempts, with me feeding back the errors. I'm wondering if it's impossible.

Write a TypeScript function that prints its input parameter keys. The function has type parameters O and L, where O is any object and L is an array of keys of O. keys has type L, and the function can infer the type of L from keys, so that L need not be explicitly specified. Moreover, I need to be able to explicitly provide O in order to constrain the keys in keys. I'll be replacing the body of the function with code that uses L. The function does not take an instance of O.

interface Person { name: string; age: number; evil: boolean; }

function printKeys<O, L>(keys: L) { ... }

// example usage
printKeys<Person>(["name", "age"]); // typechecks
printKeys<Person>(["location"]); // type error
inner crow
#

you can't partially apply parameters in a type parameter list. you either have to let them all be inferred or specify all of them

#

you can however curry the function signature to break it into two parameter lists

#

but i'm wondering if you actually need to genericize L in the first place?

#

like does this do what you need?

trail vesselBOT
#
interface Person { name: string; age: number; evil: boolean; }

function printKeys<O>(keys: readonly (keyof O)[]) {}

// example usage
printKeys<Person>(["name", "age"]); // typechecks
printKeys<Person>(["location"]); // type error
//                 ^^^^^^^^^^
// Type '"location"' is not assignable to type 'keyof Person'.
marsh crypt
#

Yeah, rule of thumb with generics, they should be used at least twice. (Counting the return signature, which may be implicit)

inner crow
#

well-said. i also question O for the same reason... it's not bound directly at all in the signature

#

some example call sites might help drive this conversation

sinful bone
#

Oh, that explains it. Actually, I had ChatGPT working with a function, but I actually need to parameterize a class and options passed to its constructor.

#

L would be the type of an option.

inner crow
#

that should be the same general idea, but you can't curry a constructor so the workaround i mentioned doesn't make sense there

inner crow
sinful bone
#

My class wraps a SQL table. An option can specify the columns that will be returned upon inserting into the table. A method will restrict its output to those columns, under certain conditions. I'm trying to make it so the user need only specify the returned columns in an argument to the constructor without also having to specify them in the type params. But the method is constrained to only returning columns of the table, and the class takes an interface providing those columns. Okay, late for an appt, will check back later...

inner crow
#

thanks, that's very helpful. some more questions for when you're back:

#

with your Person example, the method would only ever be allowed to return 'name' | 'age' | 'evil', but under certain conditions it is constrained to return 'name' | 'age'? do i have that right?

#

what are the "certian conditions" exactly? does the method take parameters that affect its behavior or are you talking about something else?

#

are you willing to share some example code that uses this class (and the class itself, if you have any part of it written already)? it will be much easier to help you with a tangible example that we can bounce back and forth

sinful bone
#

I'll finish up a version that works without inferring the return column and share that, so there's no question about what I'm up to. Thanks for your help! I'll be back when it's ready.

#

*the return colums (plural)

sinful bone
#

Hey @inner crow, this tip of yours was all I needed: "you can't partially apply parameters in a type parameter list. you either have to let them all be inferred or specify all of them."

I have everything working as I desire. The class has seven type parameters, and it will infer all of them from a provided options. Just amazing.

It's still a work in progress, and I have no docs yet, but if you want to see what I've been working on, here are the relevant files: https://github.com/jtlapp/fieldzoo/tree/main/utils/kysely-facets/src/facets

It uses Kysely, which strictly propagates RDBMS schemas through a SQL query builder, even down to the strings used to refer to tables and columns and cross-table references. This library, kysely-facets, is an attempt to provide a foundation for eliminating boilerplate without providing the restrictions query performance penalties typical of an ORM.

Thank you for your help!

GitHub

A platform for collaboratively developing online field guides and multi-branching taxonomic keys, wherein I learn React and DDD - fieldzoo/utils/kysely-facets/src/facets at main · jtlapp/fieldzoo