I'm trying to write a TypeScript type definition file for the node-serialport library. The library exports a parsers
variable with two functions, raw
and readline
. The latter cannot be used as a parser directly - it produces a parser when invoked. This is a fragment of my first attempt at a type definition file:
/// <reference path="./node.d.ts" />
declare module "serialport" {
import events = module("events");
export interface ParserFunc {
(eventEmitter: events.NodeEventEmitter, buffer: NodeBuffer): void;
}
interface Parsers {
raw: ParserFunc;
readline(delimiter?: string): ParserFunc;
}
export var parsers: Parsers;
}
The problem I'm running into is that tsc doesn't warn if I assign parsers.readline
to a variable of ParserFunc
type. To illustrate, consider the following TypeScript file:
import sp = module("serialport");
var a: number = sp.parsers.raw; // not ok
var b: number = sp.parsers.readline; // not ok
var c: sp.ParserFunc = sp.parsers.raw; // ok!
var d: sp.ParserFunc = sp.parsers.readline; // not ok
When I compile/transpile this file using tsc, I get:
test1.ts(3,16): Cannot convert 'sp.ParserFunc' to 'number'
test1.ts(4,16): Cannot convert '(delimiter?: string) => sp.ParserFunc' to 'number'
But no warning for the assignment to d
! If I make the delimiter
parameter of readline
required by removing the ?
, I get:
test1.ts(3,16): Cannot convert 'sp.ParserFunc' to 'number'
test1.ts(4,16): Cannot convert '(delimiter: string) => sp.ParserFunc' to 'number'
test1.ts(6,23): Cannot convert '(delimiter: string) => sp.ParserFunc' to 'sp.ParserFunc': Call signatures of types '(delimiter: string) => ParserFunc' and 'ParserFunc' are incompatible:
Type 'String' is missing property 'addListener' from type 'NodeEventEmitter'
So NOW it detects that the assignment to d
is invalid. But why not before?
This is my first encounter with TypeScript whatsoever, so please be gentle. Thanks! :-)
This does look like a bug to me. It looks like the compiler has assumed you are calling the function when you aren't.
I can recreate this with the simplified example:
declare module serialport {
export interface ParserFunc {
(eventEmitter: number, buffer: string): void;
}
interface Parsers {
raw: ParserFunc;
readline(delimiter?: string): ParserFunc;
}
export var parsers: Parsers;
}
var c: serialport.ParserFunc = serialport.parsers.raw; // ok!
var d: serialport.ParserFunc = serialport.parsers.readline; // not ok
So if readline was actually called, this would be valid - but actually readline is being passed without being called so it should show an error.
You can raise bugs on the TypeScript Codeplex website.