Question

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! :-)

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top