#Having trouble constraining the output of this function

14 messages · Page 1 of 1 (latest)

violet hillBOT
#
Nephy#3093

Preview:```ts
interface ObjA {
[x: string]: any
}

type ObjB<T extends ObjA> = {
[Property in keyof T]: any
}

function createNewObject<T extends ObjA>(input: T) {
const keys = Object.keys(input) as Array<keyof T>

// create objB with keys from objA
const objB = keys.reduce(
(acc, key) => ({...acc, [key]: "some value"}),
{} as ObjB<T>
...```

cosmic hornet
#

autocomplete is not working, and it allows access to properties that do not exist

fast rampart
#

it's because you have annotated the type of myObject to be the very-general ObjA. using a type annotation tells typescript to forget any additional information that it might know about the value and assign it exactly that type. so it's just the index signature from ObjA

#

if you instead let type inference do its job then you get the error you expect:

violet hillBOT
#
mkantor#7432

Preview:```ts
interface ObjA {
[x: string]: any
}

type ObjB<T extends ObjA> = {
[Property in keyof T]: any
}

function createNewObject<T extends ObjA>(input: T) {
const keys = Object.keys(input) as Array<keyof T>

// create objB with keys from objA
const objB = keys.reduce(
(acc, key) => ({...acc, [key]: "some value"}),
{} as ObjB<T>
...```

fast rampart
#

it'd also work if you annotated myObject with a more specific type

#

or maybe you meant something like const myObject = ... satisfies ObjA (which is kind of pointless in this example, but i'm not sure what you real code looks like)

cosmic hornet
#

ok awesome thanks for the help. Any chance you could show me an example of using satisfies?

In my actual code createNewObject is a function useForm that accepts initial form data and returns context related to each field. so i create a context object with the same keys as initial data.

violet hillBOT
#
Nephy#3093

Preview:```ts
interface InitialData {
[x: string]: any
}

type FormFieldContext<T extends InitialData> = {
[Property in keyof T]: any
}

function useForm<T extends InitialData>(
initialData: T
) {
const keys = Object.keys(initialData) as Array<
keyof T

// create objB with keys from objA
const formFieldsCon
...```

fast rampart
#

the general idea is as follows:

const a: Foo = b

means "check that b conforms to type Foo, and give the variable a type Foo"

const a = b satisfies Foo

means "check that b conforms to type Foo, and use normal type inference rules to assign a type to a"

#

do you need to write an explicit type at assignment time of myObject though? that InitialData type is very vague so it doesn't seem like it buys you anything to add an extra type check there. if for whatever reason you assigned null or something to myObject it would be flagged when you try to pass it to useForm anyway

cosmic hornet
#

initialData I guess could be thought of as a form schema with field names and possible initial values for the field.

for example, if you wanted to edit a user. You would pass a form schema object

const formSchema: UserSchema = {
  name: 'Joe',
  email: 'example@ex.com',
}

and thanks for the info on satisfies I am going to look into that more.

fast rampart
#

oh, InitialData isn't the real type you're using? but still, why do you need to write : UserSchema there at all? typescript will infer the type from the value