简体   繁体   中英

Is there a way in Typescript to instantiate a Record<K, V> by assignment in a generic function<T> where: T extends an object-type and K = keyof T?

What I'm trying to do is this:

interface A {
    a: number
    b: number
}

function f<T extends A>() {
    const x: Partial<Record<keyof T, string>> = {a: 'generz'}
    console.log(x)
}

But, when compiling (using tsc v4.9.3 ) I get this error message:

error TS2322: Type '{ a: "generz"; }' is not assignable to type 'Partial<Record<keyof T, string>>'.

I don't understand why and I would like to have an explanation on this error. If T extends A then keyof T is a superset of keyof A (containing at least 'a'|'b' ), so the {a: 'generz'} would be legal independently of T ? Am i missing something?


I've found out, that creating a custom PartialRecord type (described here ) like this:

type PartialRecord<K extends keyof any, T> = {
    [P in K]?: T
}

And then changing the type of variable x to PartialRecord<keyof T, string> , like this:

const x: PartialRecord<keyof T, string> = {a: 'generz'}

Compiles the code without complaining.


Update 2022-11-25

This would be equivalent code and it compiles too:

const x: Partial<Record<keyof T, string>> = {}
x.a = 'generz'

Although is not what i'll like to do.


Update 2022-11-29

What I'm asking is NOT "how to make it work in alternative ways", but is "why it doesn't work that way" , since I expect it to work. Otherwise I'd just do {a: 'generz'} as Partial<Record<keyof T, string>> (or worse as any ).

And if it wasn't clear: the code is nothing more than the minimum necessary to reproduce the error. So its purpose is not to make sense or do anything useful.

Nesting a Record<keyof T, string> inside a Partial leads to a level of abstraction which can not be properly understood by the compiler. Both Record and Partial are implemented as mapped types which can not be fully resolved when a yet unspecified generic type is supplied.

While the logic behind your assignment might be sound, it requires higher level reasoning by the compiler about the implications of nesting Record<keyof T, string> inside a Partial . Yet, it seems to be inable reason about this type at all leaving it essentially opaque . No expression would identify this type as a valid assignment target leaving only a type assertion as a workaround.

There have been multiple open issues about these higher order type problems like #43846 where Partial being wrapped around Omit lead to the same error or #28884 where an intersection of Pick<T, Exclude<keyof T, K>> & Pick<T, Extract<keyof T, K>> was not assignable to T . The compiler would fail to properly evalaute the generic types leaving them opaque, even though these operations a reasonable and mostly sound to us.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM