TypeScript object literal type assertion with generics
Asked Answered
A

3

6

I have a TypeScript class like so:

class Foo<Props extends {}> {
    public readonly props: Props;
    public readonly otherStuff: string[];

    constructor(properties: Props | string[], otherStuff?: string[]) {
      if (properties instanceof Array) {
        this.otherStuff = properties;
        this.props = {} as Props;
      } else {
        this.props = properties;
        this.otherStuff = otherStuff || [];
      }
    }
}

The problem is that this results in a no-object-literal-type-assertion rule failure in tslint (on the this.props = {} as Props line). If I remove the as Props part I get an error that {} isn't assignable to type Props.

How would you go about setting this up without disabling that tslint rule?

For reference, here's an expected usage:

type X = { foo: string; }

const foo = new Foo<X>({ foo: 'bar' });
const foo2 = new Foo(['']);
Aforetime answered 24/8, 2017 at 5:12 Comment(5)
I'm a little rusty on TypeScript at the moment, but would this.props = <Props>{}; work?Amylum
@Amylum yes, it can be written that way but it then violates palantir.github.io/tslint/rules/no-angle-bracket-type-assertion ;)Aforetime
Ok, thought that might have been a little too obvious. I've only used the angle brackets type assertions when I was last using TypeScript regularly.Amylum
Do you actually need that? Why not give props a default value so you don't have this checkingMacintosh
@Macintosh It's implementing a constructor overload approach, where the props are optional.Aforetime
C
-1

I think TSLint is actually saving you here. Let's say the warning wasn't there, and you did this:

interface X { someProperty: number };
var foo = new Foo<X>(['']);
var bar: number = foo.props.someProperty;

Even though someProperty isn't optional, it would be returning undefined - the fact is {} is not assignable to a variable of typeX and tslint is rightly stopping you in your tracks.

I'd reconsider your approach to whatever problem you're trying to solve here.

Camilacamile answered 24/8, 2017 at 6:27 Comment(0)
C
1

Could you do:

public props: Props | {}

Codger answered 24/8, 2017 at 5:34 Comment(0)
P
0

Maybe:

 this.props = new Props();
Punch answered 24/8, 2017 at 5:26 Comment(1)
This is making the assumption that Props is a constructable type, which based on the generic restriction it is not, this is a valid Props object: { foo: 'bar' }Aforetime
C
-1

I think TSLint is actually saving you here. Let's say the warning wasn't there, and you did this:

interface X { someProperty: number };
var foo = new Foo<X>(['']);
var bar: number = foo.props.someProperty;

Even though someProperty isn't optional, it would be returning undefined - the fact is {} is not assignable to a variable of typeX and tslint is rightly stopping you in your tracks.

I'd reconsider your approach to whatever problem you're trying to solve here.

Camilacamile answered 24/8, 2017 at 6:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.