using React component library without #types - reactjs

I'm developing React with TypeScript
What I want to do is to use React component library without #types definition.
I'd like to use this library
https://github.com/react-component/calendar
In my React code, I wrote as below
import * as React from "react";
import * as ReactDOM from "react-dom";
import Calendar from 'rc-calendar';
ReactDOM.render(<Calendar />, document.getElementById('content'));
but I get error:
ERROR in ./index.tsx
(4,22): error TS2307: Cannot find module 'rc-calendar'.
I'm guessing this is because there is no type definition but the library above seems not have type definition file for typescript.
How could I use such library with TypeScript?

In TypeScript 2.1, unless you're using --noImplicitAny, you will be able to just use this library without declaration files (provided that it's installed).
But since TS 2.1 isn't out yet, what you can do is create a file called externals.d.ts with the following content:
declare module "rc-calendar";
That basically tells TypeScript "hey, this thing exists, stop bugging me, and I want to use it however I want."
You can also give it a slightly better shape.
declare module "rc-calendar" {
declare var calendar: any;
export default calendar;
}
Now this thing can only be imported as a default import.
You can continue fleshing this thing out until it is sufficiently detailed.

Related

Import SVG vs. Require SVG

I'm working on a React project, and creating a component called SVGLogo that simply imports an svg and exports as a component. I noticed that when I use require() to import my svg file, it works fine:
const SVGLogo = require('../../../../../vft-site/src/images/logo.svg');
But my linter suggests I use the import statement. I changed it but now I get the error 'cannot find module... or its corresponding type declarations':
import SVGLogo from '../../../../../vft-site/src/images/logo.svg';
Why are these different?
import comes in es6 like a new feature and require can be called from anywhere but import can be called on top of script

most streamlined approach for returning jsx from basic ts file?

I'm trying to encapsulate/delegate some configuration for a custom Grid in a separate TypeScript class. The JavaScript object configurations are easy to split out into the separate class. However, I'd also like to return some jsx from that TypeScript file. What would be the most streamlined way to go about doing this? Let's say that I've created a ts file named GridConfig.ts with the following implementation:
import JSX from 'react';
export class GridConfig {
// what is the most lightweight implementation to return the jsx below?
getSomeJsx() {
return (
<tr><td>TEST</td></tr>
)
}
}
The TypeScript compiler will do this for you. There's a page in the TypeScript docs on this.
Call your file GridConfig.tsx and in the compiler options (in tsconfig.json if you have one) set 'jsx' to 'react'. You'll need to import React and ReactDOM in the tsx file.
The compiler will then turn your JSX into a React.createElement call, and TypeScript will think you are returning a type of JSX.Element.

How to export module properly so vscode can show my module in suggestion [ctrl+space]?

I have a setting style file like:
GlobalStyles.js
export const GlobalStyles={
ViewContainer:{flex:1, justifyContent:'center', alignItems:'center'},
Center:{justifyContent:'center', alignItems:'center'},
FontNormal:15,
FontMedium:18,
FontLarge:28,
FontHeader:38
}
module.export={GlobalStyles}
and when i used it in another JS file, let say Home.js. i want to vscode know every Key:Value i've defined,
with those export in GlobalStyles.js vscode suggesting an import style like this:
import { GlobalStyles } from '../Component/GlobalStyles';
and my expected result is something like:
import { ViewContainer, Center, FontMedium, [and so on]} from '../Component/GlobalStyles';
how to let vscode suggesting me Auto Import foo from path/to/GlobalStyles when i'm typing foo? where foo is like ViewContainer, Center, FontMedium, [and so on].
The feature you're talking about is called Auto Imports. To answer your question, this feature exists and works by default in VSCode.
Here is a sample of how i've used it in a React project. Here I have a component inside a folder with the same name. Outside of that folder is a file I called ModuleExports.js and it currently has the following code.
import Navbar from "./Navbar/Navbar";
export { Navbar };
For reference, export is an alias of module.export so feel free to use them interchangeably. This is a component so when I try to use it as such you can see from the screenshot I am suggested an import to use.
The same can be done without being a component. I'll declare a testObject inside the same file ModuleExports.js and export it.
Then let's see if intellisense will pick it up.
There it is. I hope this helps and do ask if you want more clarification or are running into issues.
In this case, the mistake seems to be using dynamic export. That's old CommonJs style. VSCode uses typescript tools for static analysis. To take advantage of that, you have to use ES6 export.
CommonJs: module.export={GlobalStyles}
ES6-modules: export GlobalStyles
The significant difference between two is that CommonJs variant is simply variable which is defined at runtime. Ie. there is no way to know what you are exporting without executing the code. ES6 export is reserved word. It's construct which cant be changed after definition which also means, it's type definition can be found without actually executing the code.
Typescript, Babel etc provide interoperability between two module systems but they are two very different things by spec.

How can I use multiple wildcards in Typescript module declarations?

In my ReactJS project I use the svg-transform-loader package in WebPack which updates some colors of my SVGs on the fly.
import starOutlineIcon from 'images/star-outline.svg'
import greyStarOutlineIcon from 'images/star-outline.svg?stroke=#888888'
This works pretty well and I have been using that for a while.
However I've started typing my code using TypeScript (v3.4.5) and I had to use a custom type for images:
declare module '*.svg' {
const content: string
export default content
}
I wanted to do the same thing for the transformed SVG, however the module declaration syntax does not support multiple wildcards:
declare module '*.svg?stroke=*' {
const content: string
export default content
}
However this breaks when I use tsc:
error TS5061: Pattern '*.svg*' can have at most one '*' character.
Any idea on how I could declare those modules?

Why do I have to use "require" instead of "import from" for an image in React?

I see that this answer suggests the syntax for importing images as shown below (commented out). In my case, it didn't work out (complaining there's no modules to find in that file) and I had to switch to the syntax that's currently active.
// import Author from "../assets/author.png";
var Author = require("../assets/author.png");
The difference I can imagine is that I'm using TypeScript (transpiling my TSX by awesome-typescript-loader and loading my PNG file-loader) and they seem to use JSX. But as far my understanding goes, it all transpiles to plain JS and require in the end.
Being a noob on React, I'm not sure what the reason of this discrepancy is but also I'm not sure what to google for to investigate myself.
This is more of a problem with typescript than webpack itself, you might need to declare modules on a declaration file.
Create a declarations.d.ts
Update your tsconfig.json
"include": [
"./declarations.d.ts",
],
Put this on that file:
declare module '*.png';
Error might be gone.
You can declare a module for your images like this:
declare module "*.png" {
const value: any;
export default value;
}
Then, you will be able to import your image like this:
import AuthorSrc from "../assets/author.png";
This is happening because webpack doesn't support image import out of the box. So you need to add a rule for that in the webpack config file. When you add a new rule, TypeScript doesn't automatically know that, so you need to declare a new module to resolve this. Without the module, you will be able to import images, but TypeScript will throw an error because you didn't tell to it is possible.
This issue has nothing to do with webpack or any bundler and is not quite a problem with typescript.
Typescript has stated that `require("path") is a way to include modules to the scope of your current module, whilst it can be also used to read some random files (such as json files, for example).
As Vincent and Playma256 specified, you can declare a module wildcard to match certain file types, so you can import it as an import statement. But you don't really need to do this. Typescript won't give you an error if you are trying to import a png or a json file (tslint might, but that depends on your configuration).
By the way, if your declaration is within the source folder of your project as defined in tsconfig.json, you don't need to include it as specified by Playma256.
I've created a sample project in node for you to test:
https://github.com/rodrigoelp/typescript-declare-files
I think you can solve this problem with Webpack&&typescript.The official webpage of webpack has introduced something about this in
https://webpack.js.org/guides/typescript/
And I have try this myself in
https://github.com/reactpersopnal/webpack-root/tree/feature/typescript
The reason is that you would like to use non-code assets with TypeScript, so we need to defer the type for these imports for webpack.
Your could simply add custom.d.ts.
declare module "*.jpg" {
const content: any;
export default content;
}

Resources