Brain.js has no typings.
In VSCode when importing brain.js
2
Typings should have been found and used
Please create typings for this module. Using Typescript when working with NN is awesome, because it lets you define shapes of the data you use and catch bugs early, however by using TS you lose IntelliSense because typings don't yet exist for brain.js.
So we don't have typing at this moment, but...

We do have jsdoc, which is strongly typed. This means we could easily use something like: https://www.npmjs.com/package/tsd-jsdoc and generate the typescript types on the fly
the tsd-jsdoc module doesn't work for this project, unless I'm doing something wrong.
PS C:\Programovani\brain.js\src> npx jsdoc -t ../node_modules/tsd-jsdoc -r -d typings .
npx: installed 1 in 1.471s
The "path" argument must be of type string
C:\Programovani\brain.js\node_modules\jsdoc\jsdoc.js
ERROR: Unable to parse a tag's type expression for source file C:\Programovani\brain.js\src\cross-validate.js in line 45 }": Expected ",", ":", "=", "[]" or "}" but "P" found.
ERROR: Unable to parse a tag's type expression for source file C:\Programovani\brain.js\src\cross-validate.js in line 73 }": Expected ",", ":", "=", "[]" or "}" but "P" found.
ERROR: Unable to parse a tag's type expression for source file C:\Programovani\brain.js\src\neural-network-gpu.js in line 342 with tag title "return" and text "{ data, status, endTime }": Invalid type expression "data, status, endTime": Expected "!", "#", "$", "(", "-", ".", "/", "0", ":", "<", "=", "?", "@", "[]", "\\", "\u200C", "\u200D", "_", "|", "~", Unicode combining mark, Unicode decimal number, Unicode letter number, Unicode lowercase letter, Unicode modifier letter, Unicode other letter, Unicode punctuation connector, Unicode titlecase letter, Unicode uppercase letter, [1-9] or end of input but "," found.
ERROR: Unable to parse a tag's type expression for source file C:\Programovani\brain.js\src\neural-network-gpu.js in line 349 with tag title "return" and text "{ data, status, endTime }": Invalid type expression "data, status, endTime": Expected "!", "#", "$", "(", "-", ".", "/", "0", ":", "<", "=", "?", "@", "[]", "\\", "\u200C", "\u200D", "_", "|", "~", Unicode combining mark, Unicode decimal number, Unicode letter number, Unicode lowercase letter, Unicode modifier letter, Unicode other letter, Unicode punctuation connector, Unicode titlecase letter, Unicode uppercase letter, [1-9] or end of input but "," found.
ERROR: Unable to parse a tag's type expression for source file C:\Programovani\brain.js\src\neural-network.js in line 411 with tag title "return" and text "{ data, status, endTime }": Invalid type expression "data, status, endTime": Expected "!", "#", "$", "(", "-", ".", "/", "0", ":", "<", "=", "?", "@", "[]", "\\", "\u200C", "\u200D", "_", "|", "~", Unicode combining mark, Unicode decimal number, Unicode letter number, Unicode lowercase letter, Unicode modifier letter, Unicode other letter, Unicode punctuation connector, Unicode titlecase letter, Unicode uppercase letter, [1-9] or end of input but "," found.
ERROR: Unable to parse a tag's type expression for source file C:\Programovani\brain.js\src\neural-network.js in line 418 with tag title "return" and text "{ data, status, endTime }": Invalid type expression "data, status, endTime": Expected "!", "#", "$", "(", "-", ".", "/", "0", ":", "<", "=", "?", "@", "[]", "\\", "\u200C", "\u200D", "_", "|", "~", Unicode combining mark, Unicode decimal number, Unicode letter number, Unicode lowercase letter, Unicode modifier letter, Unicode other letter, Unicode punctuation connector, Unicode titlecase letter, Unicode uppercase letter, [1-9] or end of input but "," found.
ERROR: Unable to parse a tag's type expression for source file C:\Programovani\brain.js\src\recurrent\rnn.js in line 737 with tag title "param" and text "{*[]} data": Invalid type expression "*[]": Expected "!", "=", "?", "|" or end of input but "[" found.
ERROR: Unable to parse a tag's type expression for source file C:\Programovani\brain.js\src\recurrent\rnn.js in line 742 with tag title "param" and text "{*[]} data": Invalid type expression "*[]": Expected "!", "=", "?", "|" or end of input but "[" found.
ERROR: Unable to parse a tag's type expression for source file C:\Programovani\brain.js\src\recurrent\rnn.js in line 779 with tag title "param" and text "{*[]} input": Invalid type expression "*[]": Expected "!", "=", "?", "|" or end of input but "[" found.
ERROR: Unable to parse a tag's type expression for source file C:\Programovani\brain.js\src\recurrent\rnn.js in line 779 with tag title "param" and text "{*[]} output": Invalid type expression "*[]": Expected "!", "=", "?", "|" or end of input but "[" found.
ERROR: Unable to parse a tag's type expression for source file C:\Programovani\brain.js\src\recurrent\rnn.js in line 785 with tag title "param" and text "{*[]} input": Invalid type expression "*[]": Expected "!", "=", "?", "|" or end of input but "[" found.
ERROR: Unable to parse a tag's type expression for source file C:\Programovani\brain.js\src\recurrent\rnn.js in line 785 with tag title "param" and text "{*[]} output": Invalid type expression "*[]": Expected "!", "=", "?", "|" or end of input but "[" found.
[TSD-JSDoc] Unable to resolve type name "NeuralNetwork". No type found with that name, defaulting to "any".
[TSD-JSDoc] Unable to resolve type name "object". No type found with that name, defaulting to "any".
[TSD-JSDoc] Unable to resolve type name "object". No type found with that name, defaulting to "any".
[TSD-JSDoc] Unable to resolve type name "object". No type found with that name, defaulting to "any".
[TSD-JSDoc] Unable to resolve type name "object". No type found with that name, defaulting to "any".
[TSD-JSDoc] Unable to resolve memberof for "module.exports", using memberof "module". No such name found.
[TSD-JSDoc] Unable to resolve type name "NeuralNetwork". No type found with that name, defaulting to "any".
[TSD-JSDoc] Unable to resolve type name "object". No type found with that name, defaulting to "any".
[TSD-JSDoc] Unable to resolve type name "object". No type found with that name, defaulting to "any".
[TSD-JSDoc] Unable to resolve type name "object". No type found with that name, defaulting to "any".
[TSD-JSDoc] Unable to resolve function return type for longname "module.exports". Type is not well-formed, defaulting to any.
[TSD-JSDoc] Unable to resolve memberof for "module.exports", using memberof "module". No such name found.
[TSD-JSDoc] Unable to resolve type name "NeuralNetwork". No type found with that name, defaulting to "any".
Cannot read property 'type' of undefined
and no output is generated
Likely it may be cleanup on our part. Do you have a branch were your work is being done? This is very important, imo.
No, unfortunately I don't have a branch, I'm just trying out the tools available for converting JSDoc to TS typings, sadly to no avail. I'll try poking around some more.
Okay, so dts-make generates some typigns, however they are pretty horrid-looking. There are options for it though, so maybe configuring it would improve the typings.
Repro:
Update:
dts-make is a no-go, doesn't leverage existing JSDoc and produces garbage.
Let's try https://github.com/Microsoft/dts-gen
next
From there project's readme:
This trade-off comes with a price -- you'll see a lot of anys
I don't mind trying it, but if there is something we can fix in documentation that makes that would fix this, I think there is value there as well.
Checking this out now.
I think I see the problem, you are on windows, and I don't believe dtsmake supports it. I just got the following on vanilla develop branch using your above commands:
file: neural-network.d.ts
// Type definitions for ./src/neural-network.js
// Project: [LIBRARY_URL_HERE]
// Definitions by: [YOUR_NAME_HERE] <[YOUR_URL_HERE]>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
declare namespace NeuralNetwork.prototype{
// NeuralNetwork.prototype.run.!ret
type RunRet = Array<any>;
}
declare namespace NeuralNetwork.prototype{
// NeuralNetwork.prototype._verifyIsInitialized.!0
type _verifyIsInitialized0 = Array</* NeuralNetwork.prototype._verifyIsInitialized._verifyIsInitialized0I */ any>;
}
declare namespace NeuralNetwork.prototype._verifyIsInitialized{
// NeuralNetwork.prototype._verifyIsInitialized.!0.<i>
/**
*
*/
interface _verifyIsInitialized0I {
/**
*
*/
actual : number;
}
}
declare namespace NeuralNetwork.prototype{
// NeuralNetwork.prototype._getTrainOptsJSON.!ret
/**
*
*/
interface _getTrainOptsJSONRet {
/**
*
*/
log : boolean;
}
}
declare namespace NeuralNetwork.prototype{
// NeuralNetwork.prototype._trainingTick.!1
/**
*
*/
interface _trainingTick1 {
/**
*
*/
error : number;
}
}
declare namespace NeuralNetwork.prototype{
// NeuralNetwork.prototype._prepTraining.!ret
/**
*
*/
interface _prepTrainingRet {
/**
*
*/
status : {
/**
*
*/
error : number;
/**
*
*/
iterations : number;
}
/**
*
*/
data : /* NeuralNetwork.prototype._verifyIsInitialized.!0 */ any;
}
}
declare namespace NeuralNetwork.prototype{
// NeuralNetwork.prototype.train.!ret
/**
*
*/
interface TrainRet {
/**
*
*/
error : number;
/**
*
*/
iterations : number;
}
}
declare namespace NeuralNetwork.prototype{
// NeuralNetwork.prototype.test.!ret
/**
*
*/
interface TestRet {
/**
*
*/
error : number;
/**
* for classification problems
*/
misclasses : Array<any>;
/**
*
*/
trueNeg : number;
/**
*
*/
truePos : number;
/**
*
*/
falseNeg : number;
/**
*
*/
falsePos : number;
/**
*
*/
total : number;
/**
*
*/
precision : number;
/**
*
*/
recall : number;
/**
*
*/
accuracy : number;
}
}
declare namespace NeuralNetwork.prototype{
// NeuralNetwork.prototype.toJSON.!ret
/**
*
*/
interface ToJSONRet {
/**
*
*/
layers : Array<NeuralNetwork.prototype.toJSON.!ret.LayersI>;
/**
*
*/
outputLookup : boolean;
/**
*
*/
inputLookup : boolean;
/**
*
*/
activation : string;
/**
*
*/
trainOpts : /* NeuralNetwork.prototype._getTrainOptsJSON.!ret */ any;
/**
*
*/
sizes : /* NeuralNetwork.sizes */ any;
}
}
declare namespace NeuralNetwork.prototype.ToJSONRet{
// NeuralNetwork.prototype.toJSON.!ret.layers.<i>
/**
*
*/
interface LayersI {
}
}
declare namespace NeuralNetwork.prototype{
// NeuralNetwork.prototype.createTrainStream.!0
/**
*
*/
interface CreateTrainStream0 {
/**
*
*/
neuralNetwork : NeuralNetwork;
}
}
declare namespace NeuralNetwork{
// NeuralNetwork._validateTrainingOptions.!0
/**
*
*/
interface _validateTrainingOptions0 {
/**
*
*/
log : boolean;
}
}
declare namespace NeuralNetwork{
// NeuralNetwork.weights.<i>
type WeightsI = Array<number>;
}
declare namespace NeuralNetwork{
// NeuralNetwork.changes.<i>
type ChangesI = Array<number>;
}
/**
*
*/
declare interface NeuralNetwork {
/**
*
* @param options
*/
new (options : any);
/**
* Expects this.sizes to have been set
*/
_initialize(): void;
/**
* @param activation supported inputs: 'sigmoid', 'relu', 'leaky-relu', 'tanh'
* @param activation
*/
setActivation(activation : string): void;
/**
* @returns boolean
*/
isRunnable : boolean;
/**
* @param input
* @returns {*}
* @param input
* @return
*/
run(input : any): NeuralNetwork.prototype.RunRet;
/**
* trains via sigmoid
* @param input
* @returns {*}
* @param input
*/
_runInputSigmoid(input : any): void;
/**
*
* @param input
*/
_runInputRelu(input : any): void;
/**
*
* @param input
*/
_runInputLeakyRelu(input : any): void;
/**
* @param data
* Verifies network sizes are initilaized
* If they are not it will initialize them based off the data set.
* @param data
*/
_verifyIsInitialized(data : /* [? */ any | Array</* ?] */ any> | Array<any> | _verifyIsInitialized0): void;
/**
* @param opts
* Supports all `trainDefaults` properties
* also supports:
* learningRate: (number),
* momentum: (number),
* activation: 'sigmoid', 'relu', 'leaky-relu', 'tanh'
* @param opts
*/
_updateTrainingOptions(opts : any): void;
/**
* Gets JSON of trainOpts object
* NOTE: Activation is stored directly on JSON object and not in the training options
* @return
*/
_getTrainOptsJSON(): /* NeuralNetwork.prototype._getTrainOptsJSONRet */ any;
/**
* @param log
* if a method is passed in method is used
* if false passed in nothing is logged
* @returns error
* @param log
*/
_setLogMethod(log : boolean): void;
/**
* @param data
* @returns {Number} error
* @param data
* @return
*/
_calculateTrainingError(data : any): number;
/**
* @param data
* @private
* @param data
*/
_trainPatterns(data : any): void;
/**
* @param {object} data
* @param {object} status { iterations: number, error: number }
* @param endTime
* @param data
* @param status
* @param endTime
* @return
*/
_trainingTick(data : any, status : /* NeuralNetwork.prototype._trainingTick1 */ any, endTime : any): boolean;
/**
* @param data
* @param options
* @protected
* @return { data, status, endTime }
* @param data
* @param options
* @return
*/
_prepTraining(data : /* [? */ any | Array</* ?] */ any> | Array<any>, options : any): /* NeuralNetwork.prototype._prepTrainingRet */ any;
/**
* @param data
* @param options
* @returns {{error: number, iterations: number}}
* @param data
* @param options
* @return
*/
train(data : /* [? */ any | Array</* ?] */ any> | Array<any>, options : any): NeuralNetwork.prototype.TrainRet;
/**
* @param data
* @param options
* @returns {Promise}
* @resolves {{error: number, iterations: number}}
* @rejects {{trainError: string, status: {error: number, iterations: number}}
* @param data
* @param options
* @return
*/
trainAsync(data : any, options : any): any;
/**
* @param input
* @param target
* @param input
* @param target
* @param logErrorRate
*/
_trainPattern(input : any, target : any, logErrorRate : boolean): void;
/**
* @param target
* @param target
*/
_calculateDeltasSigmoid(target : any): void;
/**
* @param target
* @param target
*/
_calculateDeltasRelu(target : any): void;
/**
* @param target
* @param target
*/
_calculateDeltasLeakyRelu(target : any): void;
/**
* Changes weights of networks
*/
_adjustWeights(): void;
/**
* @param data
* @returns {*}
* @param data
* @return
*/
_formatData(data : /* [? */ any | Array</* ?] */ any> | Array<any>): /* [? */ any;
/**
* @param data
* @returns {*}
*/
_formatData();
/**
* @param data
* @returns {*}
*/
_formatData();
/**
* @param data
* @returns {
* {
* error: number,
* misclasses: Array
* }
* }
* @param data
* @return
*/
test(data : /* [? */ any | Array</* ?] */ any> | Array<any>): NeuralNetwork.prototype.TestRet;
/**
* @returns
* {
* layers: [
* {
* x: {},
* y: {}
* },
* {
* '0': {
* bias: -0.98771313,
* weights: {
* x: 0.8374838,
* y: 1.245858
* },
* '1': {
* bias: 3.48192004,
* weights: {
* x: 1.7825821,
* y: -2.67899
* }
* }
* },
* {
* f: {
* bias: 0.27205739,
* weights: {
* '0': 1.3161821,
* '1': 2.00436
* }
* }
* }
* ]
* }
* @return
*/
toJSON(): NeuralNetwork.prototype.ToJSONRet;
/**
* @param json
* @returns {NeuralNetwork}
* @param json
* @return
*/
fromJSON(json : any): /* NeuralNetwork.prototype.+NeuralNetwork */ any;
/**
* @returns {Function}
* @return
*/
toFunction(): () => void;
/**
* @returns {Function}
*/
toFunction();
/**
* This will create a TrainStream (WriteStream) for us to send the training data to.
* @param opts training options
* @returns {TrainStream|*}
* @param opts
* @return
*/
createTrainStream(opts : NeuralNetwork.prototype.CreateTrainStream0): /* !this.trainStream */ any;
/**
*
*/
_runInputTanh : /* NeuralNetwork.runInput */ any;
/**
*
*/
_calculateDeltasTanh : /* NeuralNetwork.calculateDeltas */ any;
/**
*
*/
trainDefaults : {
/**
*
*/
iterations : number;
/**
*
*/
errorThresh : number;
/**
*
*/
log : boolean;
/**
*
*/
logPeriod : number;
/**
*
*/
learningRate : number;
/**
*
*/
momentum : number;
/**
*
*/
callbackPeriod : number;
/**
*
*/
timeout : number;
}
/**
*
*/
defaults : {
/**
*
*/
binaryThresh : number;
/**
*
*/
hiddenLayers : Array<number>;
/**
*
*/
activation : string;
}
/**
*
* @param options
*/
_validateTrainingOptions(options : /* NeuralNetwork._validateTrainingOptions0 */ any): void;
/**
*
*/
trainOpts : {
/**
*
*/
log : boolean;
}
/**
*
*/
sizes : Array<number>;
/**
*
*/
outputLayer : number;
/**
*
*/
biases : Array<any>;
/**
*
*/
weights : Array<NeuralNetwork.WeightsI>;
/**
*
*/
outputs : Array<any>;
/**
* state for training
*/
deltas : Array<any>;
/**
*
*/
changes : Array<NeuralNetwork.ChangesI>;
/**
*
*/
errors : Array<any>;
/**
*
*/
errorCheckInterval : number;
/**
*
* @param input
*/
runInput(input : any): void;
/**
* @param target
* @param target
*/
calculateDeltas(target : any): void;
/**
*
*/
activation : string;
}
I get the same output on Windows, however these typings are not 100% valid, and while fixing them by hand is possible, I don't think it's the way to go, if you take into account that you will have to manually fix typings for all the files in brain.js. I tried dts-gen, and it produces nothing for brain, and when tried on my rather simple module, produces very bad typings.
As a result of this situation, I see two possible options:
Port brain.js to Typescript
++ Can be done incrementally, i.e. just turning on type checking and gradually adding types (Vanilla JS is valid TS)
++ TS has many advantages over vanilla JS that brain.js could benefit from
+ Typings will be generated automatically
- Raises the barrier of entry for contributors
OR
Gradually add typings by hand
+ No need to port the whole project
- Must be done by hand, possibly very tiresome
- Typings have to be updated on every change to the brain API, again by hand
I think it's up to you and the team to consider these points. I will be happy to help, no matter which option you choose.
2018-04-06 10:18 GMT+03:00 Josef Vacek notifications@github.com:
I get the same output on Windows, however these typings are not 100%
valid, and while fixing them by hand is possible, I don't think it's the
way to go, if you take into account that you will have to manually fix
typings for all the files in brain.js. I tried dts-gen, and it produces
nothing for brain, and when tried on my rather simple module, produces very
bad typings.As a result of this situation, I see two possible options:
Port brain.js to Typescript
Why not Flow.js?
>
++ Can be done incrementally, i.e. just turning on type checking and
gradually adding types (Vanilla JS is valid TS)
++ TS has many advantages over vanilla JS that brain.js could benefit from
+ Typings will be generated automatically
- Raises the barrier of entry for contributorsOR
Gradually add typings by hand
+ No need to port the whole project
- Must be done by hand, possibly very tiresome
- Typings have to be updated on every change to the brain API, again by
handI think it's up to you and the team to consider these points. I will be
happy to help, no matter which option you choose.—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/BrainJS/brain.js/issues/182#issuecomment-379169543,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ACTRESk6DWBf5Cc8B7g854hRcEBwGaYEks5tlxbJgaJpZM4TC0co
.
@lagleki Here's some arguments for TS: reddit tumblr
I think TS would integrate nicely with this project, for several reasons:
1) this project uses Babel, and Babel supports TS.
1.1) this project already uses many new ES features that are transpiled via Babel, so the team should be familiar with transpiling already (or compiling in TS terms)
2) Tensorflow.js is written completely in TS, not by chance imo.
3) Plus all the arguments presented above.
I've used Typescript for several small to mid-scale projects and I have nothing but praise for it.
Flow is very similar to Typescript, but chiming in as a long-time Flow user: their main differences seem to be the amounts of libraries that have typings for them so far (I expect Typescript is winning), and Typescript seems to have more mature tooling. The type systems are similar enough that I fully expect Flow to be able to consume Typescript definition files in the future without trouble for most things (or a good automatic converter will exist).
There might be a way to produce correct typings from the JSDoc comments. I noticed VSCode suggests to add the JSDoc types as TS types, which is precisely what we want. I'll look into it some more and report back.
huzzah!
Okay, so the method I mentioned does not work as I expected. I feel we're in a kind of dead end here, and the only possible way to introduce typings is to make brain.js into a TypeScript project.
If anyone else has any ideas, please join the conversation.
Gradually add typings by hand
+ No need to port the whole project
- Must be done by hand, possibly very tiresome
- Typings have to be updated on every change to the brain API, again by hand
I think there is no way around typing stuff by hand. Sure, typings have to be kept up to date, but how often does one introduce major API changes into your package?
You also don't have to type the entire codebase, providing typings at the highest API level would be a good way to start, which could also be done gradually. As @JouzaLoL said, not having complete type information doesn't break anything.
Also by maintaining seperate type declaration files, @robertleeplummerjr and his contributors wouldn't be forced to use TypeScript in their codebase. That's the way I decided to go for my repos as well (although by now I am a huge proponent of TypeScript).
In answer to @justadudewhohacks and to this and #213, can I get someone to test and potentially collaborate on:
declare module brain {
interface INeuralNetworkDefaultOptions {
binaryThresh: number;
hiddenLayers: number[];
activation: NeuralNetworkActivation
}
type NeuralNetworkActivation = 'sigmoid' | 'relu' | 'leaky-relu' | 'tanh';
interface INeuralNetworkTrainingOptions {
iterations: number;
errorThresh: number;
log: boolean;
logPeriod: number;
learningRate: number;
momentum: number;
callback: INeuralNetworkTrainingCallback | number;
callbackPeriod: number;
timeout: number;
}
interface INeuralNetworkTrainingCallback {
(state: INeuralNetworkState): void;
}
interface INeuralNetworkState {
iterations: number;
error: number;
}
class NeuralNetwork {
public constructor(options?: INeuralNetworkDefaultOptions);
public train<T>(data: T, options?: INeuralNetworkTrainingOptions): INeuralNetworkState;
public train(data: any, options?: INeuralNetworkTrainingOptions): INeuralNetworkState;
public trainAsync<T>(data: T, options?: INeuralNetworkTrainingOptions): Promise<INeuralNetworkState>;
public trainAsync(data: any, options?: INeuralNetworkTrainingOptions): Promise<INeuralNetworkState>;
public run<T>(data: string[] | number[]): T;
public fromJSON<T>(json: T);
public toJSON<T>(): T;
}
}
add file here https://github.com/BrainJS/brain.js/tree/182-typings
Most helpful comment
So we don't have typing at this moment, but...
We do have jsdoc, which is strongly typed. This means we could easily use something like: https://www.npmjs.com/package/tsd-jsdoc and generate the typescript types on the fly