Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Working around loss of support for type constraint being self

Tags:

typescript

This is something I've been doing in older versions of TypeScript and I use this method in C#, but it doesn't work in the latest 1.0 version of TypeScript.

Here's what worked in the past:

class Base<T extends Base<T>> {
    public children : Array<T>;

    doAction() {
        this.children[0].promise(); // used to work
    }

    promise() : T {
        return this; // used to work
    }
}

class Child extends Base<Child> {
    public myString: string;
}

new Child().promise().myString; // used to work

Everything used to work in harmony.

Now in the TypeScript 1.0 I get this error on the Base<T extends Base<T>> definition:

Constraint of a type parameter cannot reference any type parameter from the same type parameter list.

How can I fix this example class to work without requiring any casts outside of the classes or casting anything to "any"? Maybe this pattern should be changed?

like image 859
David Sherret Avatar asked Apr 11 '14 03:04

David Sherret


People also ask

What are the constraints to perform your responsibilities effectively?

Constraints are the factors, within the organisation and outside it, that limit what the job-holder can do. Examples include: Resource limitations – the amounts and kinds of resources available. Legal regulations.

What are constraints in the workplace?

Common examples of constraints include insufficient information or equipment, and interruptions or inadequate help from other people.

What do you think are challenges and constraints that some organizations have?

Lack of direction is one of the most common organizational problems and it stems from two root causes: The leader or leaders rarely discuss or chart a deliberate direction or strategy for the future, or they fail to communicate a coherent message about the strategy to all members of the organization.

What are some of the common Organisational constraints that impact on training?

Though the overall definition sounds quite broad, the assessment focuses on 11 specific types of constraints: inadequate training, incorrect instruction, lack of necessary information about what to do or how to do it, poor equipment or supplies, lack of equipment or supplies, organizational rules and procedures, ...


2 Answers

You are no longer allowed to use T here:

class Base<T extends Base<T>>
--------------------------^

You either have to make your class non-generic or use:

class Base<T extends Base<any>>

The reason given for this was to make the compiler simpler:

In our continued efforts to simplify the language, we're simplifying what generic constraints can entail.

The added overhead in terms of type-checking, error-reporting, and design complexity did not add enough additional expressiveness to make it worthwhile for 1.0. We may revisit this in future versions of TypeScript.

-- Breaking Changes Wiki

like image 200
Fenton Avatar answered Oct 15 '22 20:10

Fenton


I accepted Steve's answer because he suggested to use Base<T extends Base<any>>, but I wanted to keep a copy of the code change that fixed the problem on Stack Overflow:

class Base<T extends Base<any>> { // 1. Set as any
    children: Array<T>;

    doAction() {
        this.children[0].promise();
    }

    promise(): T {
        return <any> this; // 2. cast to any
    }
}

class Child extends Base<Child> {
    public myString: string;
}

new Child().promise().myString;

This requires a cast to any, but it's not so bad since it's only in the base class. This change doesn't affect anything using the Child or Base classes, so overall it was a very ideal alternative.


Update: In TS 1.7+ this can be done using a polymorphic this:

class Base {
    children: Array<this>;

    doAction() {
        this.children[0].promise();
    }

    promise(): this {
        return this;
    }
}

class Child extends Base {
    public myString: string;
}

new Child().promise().myString;
like image 36
David Sherret Avatar answered Oct 15 '22 19:10

David Sherret