3

I have an interface

export interface ITypeAssertions
    {
         isOfTypeElseFail<TExpected extends TActual, TActual>(value: TActual, oxIsOfType: (xVal: TActual) => boolean): value is TExpected; 
    }

and implementation

export class NodeJsTestingFrameworkAdapter implements ITypeAssertions
{
  isOfTypeElseFail<TExpected extends TActual, TActual>(value: TActual, oxIsOfType: (xVal: TActual) => boolean): value is TExpected
  {
       throw new Error("Method not implemented.");
  }
}

Compiler complains that:

  • interface-not-properly-implemented

    • (...)

      • Type predicate 'value is TActual' is not assignable to 'value is TExpected'
        • Type 'TActual' is not assignable to type 'TExpected'

What's wrong? Is this a bug in a type-checker?

PS. It was compiling fine under Ts-2.3.

4
  • I'm guessing you really want the return value to be a type guard, if I change it to return bool it works for me Commented Sep 1, 2017 at 9:19
  • @TitianCernicova-Dragomir but changing the return value from value is Tto bool makes it not a generic type-guard as the OP seems to want, is it ? Commented Sep 1, 2017 at 9:25
  • 1
    Version 2.4 introduced stricter generic type inference, which might be leading to the issue. Unfortunately, it's hard for me to understand exactly why this is happening. Even stranger is the fact that it works without the user-defined type guards. I would suggest filing an issue in the official TypeScript repository. Commented Sep 1, 2017 at 10:15
  • 1
    Thanks for a tip. It has been registered as github.com/Microsoft/TypeScript/issues/18202 Commented Sep 1, 2017 at 11:12

2 Answers 2

1

Currently there is no chance to have it working, as it is described in the response under the github.com/Microsoft/TypeScript/issues/18202.

Sign up to request clarification or add additional context in comments.

1 Comment

indeed. And actually, it does reassure me a bit. I tried hard to understand how it could actually work without having some "too much loose" kind of compile check. +1 for the definitive answer from direct repo of language.
0

You have to be careful to define the interface (and not the interface method) and the class (and not the interface implementation method) as generic :

interface ITypeAssertions<TActual, TExpected extends TActual> 
{
    isOfTypeElseFail(value: TActual, oxIsOfType: (xVal: TActual) => boolean): value is TExpected; 
}

export class NodeJsTestingFrameworkAdapter<TActual, TExpected extends TActual> implements ITypeAssertions<TActual, TExpected> 
{
    isOfTypeElseFail (value: TActual, oxIsOfType: (xVal: TActual) => boolean): value is TExpected
    {
        return true;
    }
}

This compiles on the Typescript playground .

Unfortunately and as per your comment, this is not what you want, because it forces you to implement the class with each pair of types.

1 Comment

But the thing is I don't want the whole type to be parameterized; that would lead to me implementing interface for every type of object I want to test. I would need (tester: ITypeAssertions<BaseClient, ExtendedClient> = ...), (tester: ITypeAssertions<BaseTree, ExtendedTree> = ...) etc. And, as I mentioned it used to work with Ts-2.3.

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.