1

What is causing this code to fail?

interface ISomeData {
    name: string;
}

class SomeData implements ISomeData {
    name: string = "adam";
}

class SomeClass<T extends ISomeData> {
    constructor(dataTemplate?: T) {
        this.dataTemplateInternal = dataTemplate;
    }

    private dataTemplateInternal: T;

    public initSomeData() : T {
        let data: T = new SomeData();
        if (this.dataTemplateInternal) {
            return this.dataTemplateInternal;
        }
        return data;
    }
}

The first line of "initSomeData" has an error saying

Type 'SomeData' is not assignable to type 'T'

But since my generic constraint is based on an interface, which SomeData implements, shouldn't that be sufficient?

Ridiculously long link to this code in the TypeScript Playground

1 Answer 1

2

If you'd do:

let data: ISomeData = new SomeData();

You wouldn't get this error, but T is not ISomeData, it is something "more" than ISomeData, for example it can be:

interface IMoreData extends ISomeData {
    username: string;
}

And then you say that:

let data: IMoreData = new SomeData();

Which isn't right as it's missing the username property.
You can solve this by telling the compiler that you know what you're doing (AKA casting):

let data: T = new SomeData() as T;

Or just:

let data = new SomeData() as T;
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you, that was it! I was kinda thinking that's what I needed to do, not sure why I didn't just try it!
Just as a side-question, isn't the constraint stating that "your implementation must be a minimum of [THIS]" (in my case interface ISomeData { name: string }) and isn't implementing that Interface assuring that it has "name: string"? I still don't quite understand why it doesn't implicitly understand my intent there. Is that by design, or like a "todo" in the language spec? :) Nevertheless, you rock, thanks!
Yeah, the generic constraint assure that name exists in T, but T isn't ISomeData so the compiler warns you about it. If you have an instance of SomeClass<IMoreData> then the result of initSomeData should be of type IMoreData and not ISomeData

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.