Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function signature confusion after ternary operator #35707

Closed
Mickael-van-der-Beek opened this issue Dec 16, 2019 · 2 comments
Closed

Function signature confusion after ternary operator #35707

Mickael-van-der-Beek opened this issue Dec 16, 2019 · 2 comments

Comments

@Mickael-van-der-Beek
Copy link

I'm expecting this to not be a bug but I can't seem to figure out what else it could be.
Basically I'm trying to create a (TLS)Socket instance using the core Node.js net or tls modules depending on a condition.
Instantiating them by directly referencing the module works fine but whenever I introduce a level of indirection by conditionally defining the TCP client module, compilation breaks.

Code

import net from 'net';
import tls from 'tls';

const socketA = net.connect({ host: 'localhost', port: 1234 });
const socketB = tls.connect({ host: 'localhost', port: 1234 });

const protocol = process.argv[2];
const client = protocol === 'https' ? tls : net;
const socketC: net.Socket | tls.TLSSocket = client.connect({ host: 'localhost', port: 1234 });

console.log(socketA, socketB, socketC);

Expected behavior:

Successful compilation.

Actual behavior:

This expression is not callable.
  Each member of the union type
    '{ (options: NetConnectOpts, connectionListener?: (() => void) | undefined): Socket;
     (port: number, host?: string | undefined, connectionListener?: (() => void) | undefined): Socket; 
     (path: string, connectionListener?: (() => void) | undefined): Socket; } | { ...; }'
has signatures, but none of those signatures are compatible with each other.

12 const socketC = client.connect({ host: 'localhost', port: 443 });
                          ~~~~~~~

Playground Link:

Playground Link

Related Issues:

@jcalz
Copy link
Contributor

jcalz commented Dec 17, 2019

This is essentially a duplicate of #7294 (this part of which has not been fixed by #29011). If you have a union of function types and more than one of the members of the union is overloaded or generic, the compiler won't let you call it. You need to help the compiler out by manually annotating the union as a single callable signature it can verify, e.g.,

const client: {
    connect(opts: tls.ConnectionOptions & net.ConnectOpts): net.Socket | tls.TLSSocket
} = protocol === 'https' ? tls : net; // no error

const socketC = client.connect({ host: 'localhost', port: 1234 }); // okay

Playground Link

@Mickael-van-der-Beek
Copy link
Author

Thank you for the quick and complete answer. I'll keep an eye on the related issues as well. This can be closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants