添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I get this error despite the validation working. All I need is a function that generates another function using an object to filter arguments of a fixed type

Type 'keyof T' does not satisfy the constraint '"a" | "b" | "c"'.
  Type 'string' is not assignable to type '"a" | "b" | "c"'.
    Type 'keyof T' is not assignable to type '"c"'.
      Type 'string' is not assignable to type '"c"'
type GM = {
    a: number;
    b: string;
    c: string
type VMeth<T, C > = (old: T, n: C) => any;
const getVF = <T extends { [key in keyof Partial<GM>]: 1 }>(part: T):  VMeth<GM, Pick<GM, keyof T>> => {
    return function(){ } as any
const fd = getVF({ a: 1 });
fd({ a: 1, b: "", c: "s"}, { a: 1 });

Playground link

You haven't said enough about what you are trying to do, so it is rather hard to give you an answer (you also didn't ask an explicit question). The answer will depend on whether what you're doing is type-safe (in which case it's about getting the type declarations right) or not (in which case it's about getting the rest of the code right), so you need to edit the question to include all the relevant details. Please see How to Ask and minimal reproducible example. – kaya3 Mar 24, 2021 at 13:15 You're getting that error for a good reason: getVF({ a: 1, oops: 1 }); is allowed because {a: 1, oops: 1} is assignable to {a?: 1, b?: 1, c?: 1}. Perhaps you want this behavior instead (see the Fix section)? If so let me know and I'll write up an answer; if not, please edit the question to elaborate on what you're trying to do – jcalz Mar 24, 2021 at 14:04
T extends { [key in keyof Partial<GM>]: 1 }

means that T must be assignable to {a?:1, b?:1, c?:1}. This includes types you are trying to support, like {a: 1}. But it also includes types you are apparently not trying to support. Object types in TypeScript are extendable or open (as opposed to exact or closed). You are allowed to extend an object type by adding properties to it. So the type {a?: 1, b?:1, c?:1, oops: string} is also supported:

const oopsie = getVF({ a: 1, oops: "oops" }) // no error!
// const oopsie: VMeth<GM, Pick<GM, "a" | "oops">>

Because T may in fact have more keys than GM, the compiler rightfully complains that

// Type 'keyof T' does not satisfy the constraint 'keyof GM'.

If you really want to limit the keys of part to those of GM (or at least only pay attention to those keys, since object types are open no matter what you do), you can make your function generic in those keys K instead:

const getVF = <K extends keyof GM>(part: Record<K, 1>):
    VMeth<GM, Pick<GM, K>> => {
    return function () { } as any

Now K must be some subset of the union of "a" | "b" | "c" and cannot be "oops" or anything else. And so Pick<GM, K> will always work. Your desired use case still functions the same:

fd({ a: 1, b: "", c: "s" }, { a: 1 });
// const fd: (old: GM, n: Pick<GM, "a">) => any

And now we get compiler warnings if we obviously add an unexpected property:

getVF({ a: 1, oops: "oops" }); // error, excess property!

You can still manage to get such an excess property in there if you are sneaky:

const existingObj = {a: 1, oops: "oops"} as const;
const aliased: {a: 1} = existingObj;
const okay = getVF(aliased); // no error
// const okay: VMeth<GM, Pick<GM, "a">>

But at least the value that comes out is still Pick<GM, "a"> and not something invalid like Pick<GM, "a" | "oops">.

Playground link to code

I really appreciate you explaining this to me in such rich detail! I'm glad that now I have a simpler method for doing runtime type/validation checks – user5480949 Mar 24, 2021 at 15:11

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid …

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.