Minimal typescript definition for existing javascript library - javascript

I want to use the neat-csv library but it does not provide a typescript definition file. Several blogs mentioned a quick way to create a minimal definition file to get started:
declare var neatCsv: any;
But I don't know what to do with the definition file. Where should it be located? How do you link the definition file with the actual implementation which is located in node_modules/neat-csv. Then how do you import it in an actual typescript file?

The package used the following module import syntax:
const neatCsv = require('neat-csv');
This means that the kind of module is that you need don't use exports { x } of default exports export default x. What you need is the following:
declare module "neat-csv" {
var neatCsv: (input: any, options?: any) => Promise<any>;
export = neatCsv;
}
You can copy the preceding code in a file named declarations.d.ts inside your src folder. Then, you will be able to import it and use it as follows:
import * as neatCsv from "neat-csv";
let csv = "type,part\nunicorn,horn\nrainbow,pink";
neatCsv(csv, { /* options */ });

Related

Flow libdefs for libraries with deeper paths

I'm testing out Flow for typing our JavaScript, and I want to create a libdef for an internal library. It's imported like this:
import withValidation from 'internally-shared-libs/decorators/withValidation';
The documentation doesn't really address how to create library definitions for deep paths like this - only top level ones.
Where do I put the libdef file? What do I call it? And how would it look (ignoring the actual implementation of the libdef, of course)?
Thanks in advance for any help on this!
You can have multiple declare module in a single libdef. You can use a deep path as the module name. It doesn't matter where this libdef file is as long as it is included in the [libs] section in your .flowconfig.
Here's an example where internally-shared-libs has exports as well as deeper paths having exports:
Libdef:
// #flow
declare module 'internally-shared-libs' {
declare export function hello(): string;
declare export function bye(): string;
}
declare module 'internally-shared-libs/decorators/withValidation' {
// You will obviously want to improve these types
declare type Input = any;
declare type Output = any;
declare export default function withValidation(input: Input): Output;
}
Usage:
// #flow
import { hello, bye } from 'internally-shared-libs';
import withValidation from 'internally-shared-libs/decorators/withValidation';

Import JS web assembly into TypeScript

I'm trying to use wasm-clingo in my TypeScript React project. I tried to write my own d.ts file for the project:
// wasm-clingo.d.ts
declare module 'wasm-clingo' {
export const Module: any;
}
and import like this:
import { Module } from 'wasm-clingo';
but when I console.log(Module) it says undefined. What did I do wrong?
Notes:
clingo.js is the main js file.
index.html and index_amd.html are two example pages
Solution:
I solved the problem like this:
// wasm-clingo.d.ts
declare module 'wasm-clingo' {
const Clingo: (Module: any) => Promise<any>;
namespace Clingo {}
export = Clingo;
}
and
import * as Clingo from 'wasm-clingo';
Here's the source for this solution
I know you found a solution acceptable to you; however, you don't really have any types here, you just have Module declared as any, which gives you no typescript benefits at all. In a similar situation I used #types/emscripten, which provides full type definitions for web assembly modules compiled using emscripten. You simply need to do:
npm install --save-dev #types/emscripten
then change your tsconfig.json types array to add an entry for emscripten.
After that you can just write Module.ccall(...) etc. If you like you could of course write const Clingo = Module and then make calls against that if you want a more descriptive name than Module (which is a terrible name!).
You're welcome ;)
I think the issue is that wasm-clingo exports the module itself but import { Module } from 'wasm-clingo' expects a property.
Try
import Clingo_ from 'wasm-clingo';
const Clingo: typeof Clingo_ = (Clingo_ as any).default || Clingo_;

FlowTypes how to import types from private npm module

I am writing private npm package to use internally, I also want to include some flowtypes in there that will be shared between internal projects and imported in following format import type {SomeType} from 'our-private-lib' But I am having trouble in doing so, what is the best approach to include flow types with npm package?
Currently I am transpiling all ES code with babel and then also using flow-copy-source to copy original files over along side transpiled files but with .js.flow extension, but then that means that the name of these files should be the same as the transpiled file?
For example if I have file in /super-schema/index.js with
export type SuperSchemaType = {
prop1: boolean,
prop2: string
}
const SuperSchema = {
prop1: true,
prop2: 'Hello'
}
module.exports = SuperSchema;
And package.json points to main file index.js which exports SuperSchema like so
module.exports = {
superSchema: require('./super-schema.js/index.js');
}
I then can import that like so
import {superSchema} from 'our-private-lib';
but what about flowtype? import type { SuperSchemaType } from 'our-private-lib'; Doesn't really work
Your general approach is correct (using flow-copy-source), but if you want to consume types out of the main entry point of your module, you need to export the types out one way or another. You can do that explicitly by doing something like
export type {
SuperSchemaType
} from './super-schema';
Or, if you're using babel 7, export type * might be useful for you
export type * from './super-schema';

Importing external dependencies in Typescript

I am a newbie in typescript/node. I have a typescript file "order.ts" from which I would like to import an external config dependency from "config.ts"
My config file code is as below
let config = {
mongoAddress: "mongodb://localhost:27017/dts",
dataDirectory: "../../data/"
};
module.exports = config;
I am importing the config file in the order file as below
import { config } from "../../config";
However I am getting the TS compiler throwing error "... file not a module". Any clues how I should I be importing my external dependency in typescript
The main part here is you want to export your object instance. You're on the right track with that, but there may be an easier way for you.
In this case something like wrapping it in a class and exporting that:
export class Config {
mongoAddress = 'mongodb://localhost:27017/dts';
dataDirectory = '../../data/';
}
Notice the export before class. The same can be applied to interfaces, enums etc. By exporting it this way you can then import it and initialise it:
import { Config } from '../config';
var c = new Config();
console.log(c.mongoAddress);
This will not make it a variable, like in your original example, but you'll simply wrap it in a class. This is also why you have to initialise it first using new Config().
Now, I'm assuming you want these properties simply to be accessed globally. And perhaps even static/readonly, so you don't have to initialise the class each time. Making use of the static typing of TypeScript, the sample would in this case be better refactored to something like this:
export class Config {
public static readonly mongoAddress: string = 'mongodb://localhost:27017/dts';
public static readonly dataDirectory: string = '../../data/';
}
With this, calling it is even less obtrusive - and very type safe:
console.log(Config.mongoAddress);
console.log(Config.dataDirectory);
Now exporting this way is just one of the options. It actually depends entirely on the library structure you're using throughout your application (or from third partie libraries, for that matter). It's a bit of dry reading, but I recommend you have a look at the different structures to get acquainted with terms like UMD and modules and how they relate to an import.
Hope this helps!
There are 2 ways you can do import and export.
1) default export
// config.ts
export const config = {
mongoAddress: "mongodb://localhost:27017/dts",
dataDirectory: "../../data/"
};
export default config;
// your other file
import configs from './config';
Note: Here you can give any name for the imported module;
2) normal export with exact declaration name while importing.
// config.ts
export const config = {
mongoAddress: "mongodb://localhost:27017/dts",
dataDirectory: "../../data/"
};
// your other file
import { config } from './config';
Note: Here you have to give the exact name of the module that you exported.
Best practices to follow while exporting configs.
create a static class with static variables in the code. Which likely means that these configs are fixed stuffs.
module.exports is the node syntax for exporting modules. Typescript has a keyword names export so you can just use this:
export const config = {
mongoAddress: "mongodb://localhost:27017/dts",
dataDirectory: "../../data/"
};

Is it possible to use nodejs style modules in typescript?

In node, I can define a module like this by setting the properties of exports object :
module.js
exports.fun = function (val) {
console.log(val);
};
and the ask for it using var module = require('module') in and the use the module.fun() function.
Is it possible to define the module in TypeScript like this:
module.ts
exports.fun = function (val :string) {
console.log(val);
};
and then import the module in some other file using node like syntax, say, import module = require('module.ts') so that it compiles to nodejs but, if now I use module.fun() in some .ts file, it should give me an error if the arguments don't match the type specified in module.ts file.
How can I do this in Typescript?
Yes it is possible to use the true js syntax. You are receiving the error since you are using the import keyword which expects the imported file to use the export keyword. If you want the js exports.foo syntax you should use var instead of import. The following will compile/work just fine:
var module = require('module.ts')
What you've described basically exactly how external modules in TypeScript work.
For example:
Animals.ts
export class Animal {
constructor(public name: string) { }
}
export function somethingElse() { /* etc */ }
Zoo.ts
import a = require('./Animals');
var lion = new a.Animal('Lion'); // Typechecked
console.log(lion.name);
Compile with --module commonjs and run zoo.js in node.

Categories

Resources