question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Some information is lost when working with keyof against type arguments

See original GitHub issue

Bug Report

🔎 Search Terms

Hard topic to search for IMO, but I tried phrases like typescript generic interface lose type information and I only found similar issues but not related.

🕗 Version & Regression Information

I was having trouble using version 4.5.5 (that we’re currently using), but I could also reproduce it in the latest version available in the playground (4.6.2). I checked versions back to 3.3.3 in the playground and they all reported the same issue.

⏯ Playground Link

Playground link with relevant code

💻 Code

// BEGIN FRAMEWORK STUFF

type ObjectKey<O, T> = {[K in keyof O]: O[K] extends T ? K : never}[keyof O & string];

interface MyInterface {
    myStringValue: string;
    myIntegerValue: number;
}

abstract class AbstractBase<O> {
    constructor(private readonly object: O) {}

    public getValue<T>(fieldName: ObjectKey<O, T>) {
        return this.object[fieldName];
    }
}

// END FRAMEWORK STUFF

// BEGIN IMPLEMENTATION STUFF

class MyType implements MyInterface {
    myStringValue = "";
    myIntegerValue = -1;
}

class MyInterfaceHolder1<I extends MyInterface> extends AbstractBase<MyInterface> {
    constructor(object: I) {
        super(object);
        this.getValue<number>("myIntegerValue");
    }
}
class MyInterfaceHolder2<I extends MyInterface> extends AbstractBase<I> {
    constructor(object: I) {
        super(object);
        this.getValue<number>("myIntegerValue"); // Argument of type 'string' is not assignable to parameter of type 'ObjectKey<I, number>'.(2345)
    }
}

// END IMPLEMENTATION STUFF

const holder1 = new MyInterfaceHolder1<MyType>(new MyType());
const value1 = holder1.getValue<number>("myIntegerValue");

const holder2 = new MyInterfaceHolder1<MyType>(new MyType());
const value2 = holder2.getValue<number>("myIntegerValue");

🙁 Actual behavior

I lose some type information within the super-class when working with a generic argument.

🙂 Expected behavior

I feel like it should be able to maintain type information here.

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:1
  • Comments:5 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
RyanCavanaughcommented, May 6, 2022

Got around to logging #48992

1reaction
RyanCavanaughcommented, May 6, 2022

There’s no way for TS to establish the higher-order relationship between what goes into type ObjectKey<O, T> = {[K in keyof O]: O[K] extends T ? K : never}[keyof O & string]; and how that relates to the provided keys. We’d need some built-in operator to be able to deduce that this is safe; being “safe by construction” is not something the checker can recognize.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Why does type Record sometimes complain about missing ...
Let's start from the implementation: type Record<K extends keyof any, T> = { [P in K]: T; };. keyof any - just means...
Read more >
How to use the keyof operator in TypeScript
The keyof operator takes an object type and produces a string or numeric literal union of its keys. A simple usage is shown...
Read more >
Documentation - Advanced Types
This page lists some of the more advanced ways in which you can model types, it works in tandem with the Utility Types...
Read more >
Master the TypeScript Keyof Type Operator | by Bytefer
This information tells us that the parameters obj and key implicitly have “any” type. To solve this problem, we can explicitly define the ......
Read more >
Advanced TypeScript Types Cheat Sheet (with Examples)
TypeScript is a typed language that allows you to specify the type of variables, function parameters, returned values, and object properties ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found