typescript
grammar
1.a
Tag add clSTAG custom tag type error
- reference
Add DECLARE namespace JSX and Declare Module ‘React’
Does not work and introduces a new TS check error
- reference
According to the HTML5 standard, any custom tag should use a definition starting with data-
- The final solution will be
<a clstag={`.... `}>{children}</a>Copy the code
Change to the following format, barely cheat the check, to the point of no error. Instead, look for ways to extend the HTMLAnchorElement property
const props = { clstag: '... ' } <a {... props}>{children}</a>Copy the code
2, about themobx-react
the@inject
Properties have been injected, but type validation is still indicating a missing property when using this component
-
See the way to avoid directly accessing props through a custom get injected property, which requires writing one more method in each component
-
Adopt the scenario, used after injecting properties! Indicates that the attribute is confirmed to exist.
const { router } = this.props.store! Copy the code
3. Add attributes to objects at run time by extension&
For example, storeProp is used in store/header
export interface IHeader {
logoPlayed: boolean
setLogoPlayed: (v: any) = > void
restoreLogoPlayed: (a)= > void
}
@storeProp({
setter: [{default:!!!!! storage.get('logoPlayed'),
name: 'logoPlayed',}]})class Header {
public headerProp = false
}
const header = new Header() as IHeader & Header
export { Header }
export default header
Copy the code
When you use the header, you get the IHeader and all the attributes in the header
4. Require that each instance’s properties have initial values, which can be set either in constructor or at declaration time
Property 'fetchBatch' has no initializer and is not definitely assigned in the constructor.
Copy the code
If a method in a normal class is defined without any implementation, the above error will be reported. One solution is to write:
public restoreBatch! :(a)= > void
Copy the code
It’s a bit of a hassle to write this every time, so you can add the following configuration to tsconfig.json:
"strictPropertyInitialization": false,
Copy the code
More seriously, however, any methods that are not implemented should not be written in ordinary classes, but in abstract ones. Therefore, when the above situation occurs, the code should be implemented as follows:
abstract class A{
public restoreBatch: (a)= > void
}
class B extends A{}
const b = new B()
export default b
Copy the code
5. Exported variables cannot be used as types, even if the variable is assigned from a class
class A {}
export const A1 = A
// other file
import { A1 } from 'A'
// A1 is only used as a variable, not as a type.
// a pit 🥵!
Copy the code
6, high order componentschildren
The type definition
For example, the children type of the SRC/Component /Permission component should be defined as children: react.reactNode. React defines the ReactNode type as:
type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;
Copy the code
7, antdForm.create()
decorator
This modifier is currently unavailable in TS and can only be replaced with function
Such as:
@Form.create()
class Test{}
Copy the code
Replaced by:
class Test{}
Form.create()(Test)
Copy the code
The official explanation
8. There are two ways to solve the following exceptions
Exception information:
Property 'store' is missing in type '{}' but required in type 'Readonly<RcBaseFormProps & Pick<IProps, "store">>'.
Copy the code
Search. TSX source code:
interface IProps {
store: {
rollbackEdit: RollbackEditStore
}
form: WrappedFormUtils
}
@inject('store')
@observer
class Search extends React.Component<IProps> {
public store: RollbackEditStore
constructor(props: IProps) {
super(props)
const {
store: { rollbackEdit },
} = this.props
this.store = rollbackEdit
}
public onChange = (value: SelectValue) = > {
const { form } = this.props
this.store.setType(value)
this.store.setList([])
form.setFieldsValue({
id: undefined, }) } public render() { ... }}export default Form.create()(Search)
Copy the code
The first solution:
Remove the constructor definition of a store reference. Add an optional question mark after the store of IProps
interface IProps { store? : {rollbackEdit: RollbackEditStore
}
form: WrappedFormUtils
}
Copy the code
Const {rollbackEdit} = this.props. Store!
The second solution:
TSX, simply pass store to it in the index. TSX call:
const store = {
rollbackEdit,
}
const RollbackEdit = (a)= > (
<Card
title={
<CardTitle>
<Search store={store} />
</CardTitle>
}
bordered={false}
>
<List />
</Card>
)
Copy the code
9. Typescript causes Webpack split chunk invalidation.
reference
With ts official website, etc., that tsconfig
module: 'commonjs'
Copy the code
Must result in code splitting effectiveness and must be configured to
module: 'esnext'
Copy the code
The commonJS package is used in webpack.config.ts, which is clearly stated in the TS documentation
export = xxxx
Copy the code
The exported package must be used
import xxx = require('xxx')
Copy the code
In the way of introduction. But as long as this package is used, esNext’s module type is not available.
Options:
- use
tsconfig-paths-webpack-plugin
And introduce another onetsconfig.json
File that the file usesesnext
Module mode. - The more concise way is in
webpack
thets-loader
addoptions
To enable the front-end compilation environment to use a different TSConfig configuration than the source environment.
options: {
compilerOptions: {
module: 'esnext',}},Copy the code
Double variability of function types
For details, see: double variability of function types
Type guard and type distinction
interface Bird {
fly();
layEggs();
}
interface Fish {
swim();
layEggs();
}
function getSmallPet() :Fish | Bird {
// ...
}
let pet = getSmallPet();
// Every member accesses an error
if (pet.swim) {
pet.swim();
}
else if (pet.fly) {
pet.fly();
}
Copy the code
To make this code work, we need to use type assertions:
let pet = getSmallPet();
if ((<Fish>pet).swim) {
(<Fish>pet).swim();
}
else {
(<Bird>pet).fly();
}
Copy the code
Notice here that we have to use type assertions multiple times. It would be nice if once we checked the type, we could clearly know the type of PET in each subsequent branch. TypeScript’s type-guarding makes this a reality. Type guards are expressions that are checked at run time to make sure the type is in a scope. To define a type guard, we simply define a function whose return value is a type predicate:
function isFish(pet: Fish | Bird) :pet is Fish {
return (<Fish>pet).swim ! == undefined; }Copy the code
In this case, pet is Fish is the type predicate. The predicate is of the form parameterName is Type. ParameterName must be a parameterName from the current function signature. Whenever isFish is called with some variable, TypeScript reduces the variable to that specific type, as long as the type is compatible with the variable’s original type.
// The 'swim' and 'fly' calls are ok now
if (isFish(pet)) {
pet.swim();
}
else {
pet.fly();
}
Copy the code
Check the type of CSS-Module
We took a deroute at first, using typescript-plugin-CSS-modules, which doesn’t support less well, breaks when using complex LESS functions, and often needs to restart tsServer when updating LESS files. Typings -for- CSS -modules-loader
Use a Webpack loader to instantly generate the corresponding.d.ts file to map CSS Modules’ classes.
TSC command line parameters
When only one file is compiled, tsconfig.json for the current project is not automatically loaded if the TSC parameter is specified. This is confusing and will generate incorrect compilation results.
14,ts-loader
withfork-ts-checker-webpack-plugin
withawesome-typescript-loader
.
Ts-loader is used independently, without command line type verification prompt, and the more items, the slower the compilation. Ts-loader needs to be used together with fork-ts-checker-webpack-plugin. It can compile files in seconds after update and display type verification on the command line, but consumes a lot of memory. Awesome-typescript-loader consumes less memory, compiles faster when files are updated, and displays command-line type validation. For example, if you are changing files that depend on more, such as the lower-level store that the View depends on, the compilation will be slightly slower.
15,typescript
withpreact
withweb component
.
You first need to add it in tsconfig.json
"jsx": "react"."jsxFactory": "h".Copy the code
When using the custom DOM in preact, you need to extend IntrinsicElements, which can be found in Google to extend JSX under Global
declare namespace JSX {
interface IntrinsicElements {
foo: any}}Copy the code
However, JSX resides in a different namespace in a Preact environment
declare global {
namespace preact {
namespace h {
namespace JSX {
interface IntrinsicElements {
'custom-node': any
}
}
}
}
}
Copy the code
configuration
16,tsconfig.json
Path alias ofpath
If it’s for your current project, feel free to use it
When used with other projects, in my case as a multi-package LerNA project, one package needs to import another package’s TS file, so the path alias in the original package does not work in the other package.
17,.d.ts
With the release
When the project is published, even if declaration in tsconfig.json is opened, the.d.ts files in it will not be automatically compiled to the directory specified by outDir
If there are definitions in the project that rely on these.d.ts, additional replication scripts need to be added during the release process
Try not to use import to introduce other dependencies in.d.ts. In particular, do not introduce the type of impure definition file, such as the actual logical code in the file, otherwise it will not work in the environment using the package after distribution
18. Compile with Babel
Because there are many abstract classes defined using Abstract in the project, the abstract classes are used only for type checking at TS-Loader compilation time. However, when compiled with Babel, the abstract class generates the real class, and its properties are generated along with the class. A collision caused by using mobx extended attributes will not run.