Reputation: 6791
I have this interface:
interface IParameters {
form: number;
field: string;
...
}
I want the form
property to be number or function and field
to be string or function.
I try something like this:
interface IParameters {
form: number | Function;
field: string | Function;
...
}
I need this because in my code i use this variables like this:
var form = (typeof _oParameters.form === "function" ? _oParameters.form() : _oParameters.form);
var field = (typeof _oParameters.field === "function" ? _oParameters.field() : _oParameters.field);
I don't want change this variable in all my code from string/number to default function and to prevent setting this variables to other types.
but if I try to call one of this two variable like function:
var param:IParameters;
param.form();
...
I get this error:
Cannot invoke an expression whose type lacks a call signature.
but param.form = 12;
works.
The only solution that i have found is to declare form
and field
to any
type.
Is other way to define this variable without any
type?
Upvotes: 12
Views: 15006
Reputation: 828
If you try to use the code from seriesOne you will notice, that you cannot assign form
(or field
) a value that isn't a function.
You would get a
Type '{ form: string; }' is not assignable to type 'IParameters'.
Types of property 'form' are incompatible.
Type 'string' is not assignable to type '() => string'.
I found that using form: (() => string) | string;
resolves this problem.
You can try the code at the typescript playground.
Working sample:
interface IParameters {
form: (() => string) | string;
}
function strFunct(): string {
return 'Hello TypeScript';
}
function test() {
let paramA: IParameters = {
form: strFunct
}
let paramB: IParameters = {
form: 'Hello stackoverflow'
}
}
class Foo {
constructor(param: IParameters) {
var x = typeof param.form === 'string' ? param.form : param.form();
}
}
Upvotes: 20
Reputation: 42380
Perhaps if you define your union type using a call signature rather than Function
, like so...
interface IParameters {
// form is of type function that returns number, or number literal.
form: () => number | number;
// field is of type function that returns a string, or string literal.
field: () => string | string;
}
class Foo {
constructor (param: IParameters) {
var x = typeof param.form === "number" ? param.form : param.form();
var y = typeof param.field === "string" ? param.field : param.field();
}
}
Here, I am still checking form
and field
using typeof
, however TypeScript is happy for it to be either a function call, or a value.
Upvotes: 7
Reputation: 11264
Upd
That behavior appears to be an issue #3812 with TypeScript.
It is to be fixed as a part of TypeScript 2.0 according to the milestone assigned.
Original answer
You could use instanceof
as a type guard like
var field = (_oParameters.field instanceof Function ? _oParameters.field() : _oParameters.field);
Upvotes: 2