Re-export all imports with changed type definition - node-modules

We have a git submodule of React components written in poorly typed TS. It has a single index file, which re-exports everything like this:
export * from './blocks'
Then, in the main app, we use import * as allBlocks from '../packages/blocks' or import {SomeBlock} ....
But now, I have added some type declarations to the mentioned index file, which, however, need to be imported separately to use.
Is there a way to tell TS to re-export as the new type?
for example something like this:
export * from './blocks' as TheNewType
This is how the index file looks currently.
export * from './blocks' // I want to export all as different type
// all this is just for the types
import * as allBlocks from './blocks'
type AllBlocks = typeof allBlocks
type BlockNames = keyof AllBlocks
export type BlockComponents = {
[key in BlockNames]: BlockComponent<ExtractComponentGenerics<AllBlocks[key]>>
}
type BlockComponent<P = {}> = React.ComponentType<P> & BlockComponentStatics<P>
/** This interface types some static properties used by our library, that are not normally present on React.ComponentType */
interface BlockComponentStatics<P = {}> {
getInitialProps?(): P | Promise<P>;
// ...
}
function assertIsBlocks(val: any): asserts val is BlockComponents {/*...*/}
assertIsBlocks(allBlocks)
export allBlocks // This unfortunatelly produces named export, which I don't want.
export default allBlocks // I don't want this neither. I want the * export.
Since this package doesn't come as a module, I am not sure if and how I can use Ambient module declaration or Module augmentation.

Related

Cannot find module even though the cypress test runner is able to mount the component

I am trying to set up component tests with cypress, vue3 and vite. With the Getting Started guide, I was able to successfully mount my component, however in my editor (vscode), it tells me that I cannot find the module or corresponding type declarations ts(2307).
I have added the global styles file in support/component.ts and nothing else.
// Import commands.js using ES2015 syntax:
import "./commands";
// Import global styles
import "../../src/styles/style.scss";
// Alternatively you can use CommonJS syntax:
// require('./commands')
import { mount } from "cypress/vue";
// Augment the Cypress namespace to include type definitions for
// your custom command.
// Alternatively, can be defined in cypress/support/component.d.ts
// with a <reference path="./component" /> at the top of your spec.
declare global {
namespace Cypress {
interface Chainable {
mount: typeof mount;
}
}
}
Cypress.Commands.add("mount", mount);
How do I get rid of the linter warning?

How to create with jscodeshift a Typescript interface

I would like to create interface with few properties but with a constructor rather than with pure text, something in this form:
const interfaceDeclaration = j.interfaceDeclaration(j.identifier("props"), /* ... */);
I have problem with ObjectTypeAnnotation and the last parameter

VSCode - Reference a type of a module from JS

Using Visual Studio Code for JS programming I can access some features from typescript; since the editor will parse all .d.ts files around, it'll help me with variable types. For example it does recognize the following:
any.js
/**
* #param {string} s
* #return {Promise<Person>}
*/
function foo(s){ ... }
foo('Jhon').then((p) => p.name )
index.d.ts
interface Person {
name: string
surname: string
}
Now, I want to access types (interfaces, classes... whatever) declared in node.d.ts declaration file; for example it declares the module stream which declares the Readable interface.
I'm looking for something like this:
const stream = require('stream')
/**
* #param {stream.Readable} stream
*/
function goo(stream) { ... }
But that does not work.I've tried with:
{internal.Readable}
{stream.Readable}
{Node.stream.Readable}
{Node.Readable}
{Node.internal.Readable}
As of VS Code 1.18, this is a limitation when using require with JSDoc types. I've opened this issue to track this specifically
Some possible workarounds:
Use import:
import * as stream from 'stream'
/**
* #param {stream.Readable} stream
*/
function goo(stream) { ... }
or import Readable explicitly:
const stream = require('stream')
const {Readable} = require('stream')
/**
* #param {Readable} stream
*/
function goo(stream) { ... }
https://github.com/Microsoft/TypeScript/issues/14377 also tracks allowing you to specify module imports in jsdocs directly.

How do I reference a Typescript enum inside a definition file

I am using Visual Studio 2013 with update 4 and Typescript 1.3 installed.
If I have a typescript file, like so:
MyEnums.ts:
export = MyEnumModule;
module MyEnumModule {
export enum AnEnum { RED, BLUE, GREEN }
}
And I have a definitions file like so:
MyDefinitions.d.ts:
declare module MyDefinitions {
interface ISomeInterface {
aProperty: string;
aMethod: () => void;
aColor: MyEnumModule.AnEnum;
}
}
I basically get an error of "Cannot find name 'MyEnumModule'"
This enum file works fine when referenced from typescript files. For instance:
SomeCode.ts:
export = MyCode;
import MyEnums = require('MyEnums');
module MyCode{
export class MyClass implements ISomeInterface {
public aColor: MyEnums.AnEnum = MyEnums.AnEnum.RED;
...and so on
My understanding is that adding either /// <reference ... or an import will not work for a .d.ts file (I tried just to be sure and it didn't appear to work either way).
Does anyone know how to reference an enum in a definition file like this?
Thanks in advance.
--Update:
Here is the error I see after trying Steve Fenton recommendations below (with a sample project I just made).
MyDefinitions.ts:
import MyEnumModule = require('../App/MyEnums');
declare module MyDefinitions {
interface ISomeInterface {
aProperty: string;
aMethod: () => void;
aColor: MyEnumModule.AnEnum;
}
}
MyEnums.ts:
export = MyEnumModule;
module MyEnumModule {
export enum AnEnum { RED, BLUE, GREEN }
}
MyClass.ts:
export = MyCode;
import MyImport = require('MyEnums');
module MyCode {
export class MyClass implements MyDefinitions.ISomeInterface {
public aColor: MyImport.AnEnum = MyImport.AnEnum.RED;
constructor() { }
aProperty: string = "";
aMethod: () => void = null;
}
}
Folder structure:
App
-MyClass.ts
-MyEnums.ts
Defintions
-MyDefintions.d.ts
Inside MyClass.ts MyDefinitions.ISomeInterface is underlined in red with hover warning "Cannot find name MyDefinitions".
I have AMD set for the project
Does anyone know how to reference an enum in a definition file like this?
There are workaround as Steve Fenton pointed out, but the system isn't designed for this. You should reference other definition files in your definition file and not reference an *implementation file * (MyEnum.ts) in a definition file.
I had a check on this and the following definition works for me, although I must admit I have never referenced "actual" code from "definition" code - but I can't think of any reason not to.
import MyEnumModule = require('MyEnumModule');
declare module MyDefinitions {
interface ISomeInterface {
aProperty: string;
aMethod: () => void;
aColor: MyEnumModule.AnEnum;
}
}
On mixing definitions and real implementations...
The type system in TypeScript is a design time and compile-time tool. When the type information is constructed at design time it makes no difference whether the type information is inferred from implementation code, taken from annotations that decorate implementations or come from an ambient declaration.
There are many use cases for mixing implementation code and ambient declarations - if you are migrating a million-line JavaScript program to TypeScript, you may not be able to migrate it from the bottom-most dependency upwards. Also, you can place ambient declarations inside of normal files - not just definition files - if you have a large program, you may not even know whether a type you place in an ambient declaration is "real" or "ambient".
The only difference between implementation code types and ambient declaration types is that the type information is right next to the implementation in real code files, and in a separate file for ambient declarations.
So... if you are having a problem using real implemented types in your ambient declaration, it is most likely caused by something that can be fixed. The example I supplied above works in a project I have in Visual Studio 2013, Update 4 - with TypeScript build configuration set to compile AMD modules. If you can share the exact details of the problem, I'm happy to help you get it working.
Having said this - if you are creating a type definition for trivial amounts of code, pasting them into a .ts file may even be faster than writing the definition - so you should make a case-by-case decision on where to spend the effort.

Package imports, cannot use struct from imported package

This is probably a noob mistake but I cannot figure this out.
In main.go I am importing a package.
import(
"models/users"
)
// ...
func main() {
r.HandleFunc("/users/list", UsersModel.List())
The package is stored in src/models/users
The users package looks like this:
package users
import (
"gopkg.in/mgo.v2"
)
// ...
/**
* User Model
*/
type UsersModel struct {
}
// Add methods to the UsersModel type.
func (m *UsersModel) List() {
// ...
When I run the code I get the following error.
src\main.go:9: imported and not used: "models/users" src\main.go:20:
undefined: UsersModel
The go code appears to be valid as if I invalidate it throws an error. How do I export the UsersModel type from the users package?
You need to prefix your use of UsersModel with the package name users, like so:
um := users.UserModel{}
UsersModel.List() is also wrong: go doesn't have "static methods" or "class methods".

Resources