My question: is there a directive in comment that would tell typescript compiler to ignore whatever it considers error in the line of code following the directive?
I was looking in typescript docs, I was googling but could not find the answer.
I have a typescript class containing some optional members, like this:
import providers from "./components.json"
import { Socket } from 'node:net'
/**
* TcpLink represents control and data communication channels
* (in some cases only control)
* to send and receive data and commands to and from
* other programs (components) that provide someuseful function:
* radio equipment control, software modem, protocol wrapper
* etc. The programs may have individual locations and other than
* default TCP ports configured and that's why the class should be
* configurable by means of a JSON file.
* In this example Socket is not used, as the question only
* related to problems in the constructor
**/
export class TcpLink {
cmd?: Socket ; // control connection socket
data?: Socket ; // data connection socket
dataPort? : number ; // data TCP port number
controlPort?: number ; // control TCP port number
name: string ; // symbolic name of the component to attach to
/** Constructor will accept provider name and retrieve parameters,
* but will not connect yet
*/
constructor( providerName : string ) {
this.name = providerName
const ports = providers[providerName as keyof typeof providers]?.ports
if( ports === undefined ) {
throw (new Error(`ERR001: component ${providerName} not defined in file components.json`))
}
else {
this.dataPort = ports.data
this.controlPort = ports.control
}
}
/* the rest of the implemenation is omitted */
}
The configuration JSON file looks like this:
{
"rigctld": {
"command": "/usr/bin/rigctld",
"ports": {
"control": 4532
}
},
"ardop": {
"command": "/home/ok4rm/.local/ardopcf",
"ports": {
"control": 8515,
"data": 8516
}
},
"vara": {
"command": "/usr/bin/wine c:/VARA/VARA.exe",
"ports": {
"control": 8301,
"data": 8300
}
}
}
rigctld is only a control program, it does not communicate any "data" and there is only one TCP connection to it, therefore it has no data attribute.
Now the problem is, if I write the line
this.dataPort = ports.data
in plain javascript, there is absolutely no problem (except there are no classes, of course) and this.dataPort
would be undefined
which is perfectly OK and later in the lifecycle is handled properly.
However, in typescript, the compiler throws this error
Property 'data' does not exist on type '{ control: number; }'.
(referring to the JSON attribute with no data
member).
It forces me to rewrite the code this way just to make it shut up:
if( 'data' in ports ) this.dataPort = ports.data
but it is just an annoying workaround for a line that would work as expected in plain javascript. (BTW there is another annoying workaround a few lines above, the assignment const ports = ...
, see also Element implicitly has an 'any' type because expression of type 'string' can't be used to index)
My question: is there a directive in comment that would tell typescript compiler to ignore whatever it considers error in the line of code following the directive?
I was looking in typescript docs, I was googling but could not find the answer.
I have a typescript class containing some optional members, like this:
import providers from "./components.json"
import { Socket } from 'node:net'
/**
* TcpLink represents control and data communication channels
* (in some cases only control)
* to send and receive data and commands to and from
* other programs (components) that provide someuseful function:
* radio equipment control, software modem, protocol wrapper
* etc. The programs may have individual locations and other than
* default TCP ports configured and that's why the class should be
* configurable by means of a JSON file.
* In this example Socket is not used, as the question only
* related to problems in the constructor
**/
export class TcpLink {
cmd?: Socket ; // control connection socket
data?: Socket ; // data connection socket
dataPort? : number ; // data TCP port number
controlPort?: number ; // control TCP port number
name: string ; // symbolic name of the component to attach to
/** Constructor will accept provider name and retrieve parameters,
* but will not connect yet
*/
constructor( providerName : string ) {
this.name = providerName
const ports = providers[providerName as keyof typeof providers]?.ports
if( ports === undefined ) {
throw (new Error(`ERR001: component ${providerName} not defined in file components.json`))
}
else {
this.dataPort = ports.data
this.controlPort = ports.control
}
}
/* the rest of the implemenation is omitted */
}
The configuration JSON file looks like this:
{
"rigctld": {
"command": "/usr/bin/rigctld",
"ports": {
"control": 4532
}
},
"ardop": {
"command": "/home/ok4rm/.local/ardopcf",
"ports": {
"control": 8515,
"data": 8516
}
},
"vara": {
"command": "/usr/bin/wine c:/VARA/VARA.exe",
"ports": {
"control": 8301,
"data": 8300
}
}
}
rigctld is only a control program, it does not communicate any "data" and there is only one TCP connection to it, therefore it has no data attribute.
Now the problem is, if I write the line
this.dataPort = ports.data
in plain javascript, there is absolutely no problem (except there are no classes, of course) and this.dataPort
would be undefined
which is perfectly OK and later in the lifecycle is handled properly.
However, in typescript, the compiler throws this error
Property 'data' does not exist on type '{ control: number; }'.
(referring to the JSON attribute with no data
member).
It forces me to rewrite the code this way just to make it shut up:
if( 'data' in ports ) this.dataPort = ports.data
but it is just an annoying workaround for a line that would work as expected in plain javascript. (BTW there is another annoying workaround a few lines above, the assignment const ports = ...
, see also Element implicitly has an 'any' type because expression of type 'string' can't be used to index)
1 Answer
Reset to default 1is there a directive in comment that would tell typescript compiler to ignore whatever it considers error in the line of code following the directive?
The direct answer to this is "yes": // @ts-ignore
or // @ts-expect-error
.
However, rather than suppressing such errors I would suggest addressing them. Your primary complaint seems to be that providers
is too narrowly-typed, which you could change like so:
import providersFromJSON from "./components.json"
type ProviderName = keyof typeof providersFromJSON
type Provider = {
command: string
ports: {
control?: number
data?: number
}
}
const providers: Record<ProviderName, Provider> = providersFromJSON
This will also help you catch future mistakes/typos in components.json
.
Additionally, to eliminate the other annoying workaround you mentioned, type providerName
more narrowly (as ProviderName
rather than string
):
constructor( providerName : ProviderName ) {
this.name = providerName
const ports = providers[providerName]?.ports
if( ports === undefined ) {
throw (new Error(`ERR001: component ${providerName} not defined in file components.json`))
}
else {
this.dataPort = ports.data
this.controlPort = ports.control
}
}
Putting all of that together, here's a complete/self-contained example.
Socket
. These are barriers for others to start working on your issue, and make it less likely that any answer you get will have been tested first. – jcalz Commented Mar 20 at 13:12