9

This may not be possible due to current language limitations, but I'm using the latest TS (1.8.10) and am running into an issue with the ui-grid typings. The isRowSelectable property on IGridOptions is defined as an optional boolean but the documentation says it's a function (and it is). I am trying to override the boolean property to be a function that returns a boolean.

Normally, I just extend the typing interface and do what I need, but that's not working in this case. Here's what I have:

interface ISelectionGridOptions extends IGridOptions {
  isRowSelectable: (row: IGridRowOf<Profile>) => boolean;
}

Where the relevant field in IGridOptions is:

export interface IGridOptions {
  ...
  isRowSelectable?: boolean
  ...
}

And the error I'm getting is:

(41,11): error TS2430: Interface 'ISelectionGridOptions' incorrectly extends interface 'IGridOptionsOf<any>'.
  Types of property 'isRowSelectable' are incompatible.
    Type '(row: IGridRowOf<Profile>) => boolean' is not assignable to type 'boolean'.

Short of fixing the core typings definitions, is there a way to fix this in my code?

icfantv
  • 4,523
  • 7
  • 36
  • 53
  • 2
    If the interface declares `isRowSelectable` to be a boolean then you can not "override" it with a function, because boolean isn't callable. – Nitzan Tomer Jun 08 '16 at 15:24
  • 1
    To be a bit pedantic, it breaks not because the boolean isn't callable, but, like the error says, because a function isn't assignable to boolean. The function peg is failing to fit into the boolean hole, not vice versa. – mk. Jun 08 '16 at 15:46
  • **See Also**: [Overriding interface property type defined in Typescript d.ts file](https://stackoverflow.com/q/41285211/1366033) – KyleMit Nov 03 '21 at 20:17

4 Answers4

20

You can use the utility type Omit: https://www.typescriptlang.org/docs/handbook/utility-types.html#omittk

interface ISelectionGridOptions extends Omit<IGridOptions, 'isRowSelectable'> {
  isRowSelectable: (row: IGridRowOf<Profile>) => boolean;
}
Diego Blattner
  • 211
  • 2
  • 2
  • IMO, this is not the right answer or solution. Sure, it's a workaround, but it doesn't address or fix the root cause of the problem which is something I would encourage any engineer to pursue. – icfantv Jan 03 '20 at 18:04
  • Agree it doesn't solve the OP's issue, but this is extremely useful for code-reuse, especially if you want to re-use something from a third party. +1 – Chris Nov 06 '20 at 22:25
6

If the type definitions are incorrect, you can't use overriding in order to fix them - the type system correctly treats this as an error. In a typed language, it's a good thing that subclasses are prevented from changing type signatures. The problem here is the broken type definition. If it's not practical to fix the def, and the issue occurs in only a few places in your code, you could use a cast to any to disable typechecking until the defs are fixed:

var foo = <boolean> (<any>bar).isRowSelectable(args);
bar.isRowSelectable = <any>foo; 

Just leave a comment explaining what's going on. It is, of course, best to fix the type defs.

Note: It breaks, like the error says, because a function isn't assignable to boolean. The function peg is failing to fit into the boolean hole, not vice versa

Dheeraj Bhaskar
  • 18,633
  • 9
  • 63
  • 66
mk.
  • 11,360
  • 6
  • 40
  • 54
  • 2
    Yea, I did my mitzvah for today and submitted a PR: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/9594 – icfantv Jun 08 '16 at 15:50
4

Update for TS 3.5+

You can add this utility type to your project:

type Modify<T, R> = Omit<T, keyof R> & R;

And then use it like this:

type ISelectionGridOptions = Modify<IGridOptions, {
  isRowSelectable: (row: IGridRowOf<Profile>) => boolean;
}>

Demo in TS Playground

Further Reading

KyleMit
  • 30,350
  • 66
  • 462
  • 664
0

You can use the Merge utility from the excellent type-fest package to override or overwrite any property on a type, regardless of it's original type:

import type {Modify} from 'type-fest'

type SelectionGridOptions = Modify<GridOptions, {
  isRowSelectable: (row: GridRow<Profile>) => boolean;
}>
rattray
  • 5,174
  • 1
  • 33
  • 27