a
标签添加clstag这种自定义标签类型错误问题添加了declare namespace JSX
和declare module 'react'
javascript
不起做用,并且引入新的ts校验错误css
按照html5标准建议,只要是自定义标签,都应使用data-
开头的定义html
<a clstag={`....`}>{children}</a>
复制代码
改成以下格式,勉强骗过校验,达到不报错的地步。 正路仍是应该寻找扩展HTMLAnchorElement属性的方法前端
const props = {
clstag: '...'
}
<a {...props}>{children}</a>
复制代码
mobx-react
的@inject
已注入属性,但在使用该组件时仍是类型校验提示缺乏属性的问题参考 经过一个自定义get injected
属性来避免直接获取props的方法,须要在每一个组件中都多写一个方法html5
采用方案,在注入属性后使用!
代表该属性确认存在。java
const { router } = this.props.store!
复制代码
&
例如在store/header
中使用了storeProp
node
export interface IHeader {
logoPlayed: boolean
setLogoPlayed: (v: any) => void
restoreLogoPlayed: () => 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
复制代码
在使用header
时便可获取IHeader
与Header
中的全部属性react
Property 'fetchBatch' has no initializer and is not definitely assigned in the constructor.
复制代码
若是一个普通类中的方法只是被定义了,而没有进行任何实现,便会报以上错误,解决办法之一是这样写:webpack
public restoreBatch!: () => void
复制代码
若是每次都这样写确实有些麻烦,因此能够在tsconfig.json
添加如下配置:git
"strictPropertyInitialization": false,
复制代码
可是,以更严谨的角度来讲,未进行实现的任何方法都不该该写在普通类里,而应该放在抽象类里。所以,遇到以上状况时,代码应该如下方式来实现:
abstract class A{
public restoreBatch: () => void
}
class B extends A{}
const b = new B()
export default b
复制代码
class A {}
export const A1 = A
// other file
import { A1 } from 'A'
// 此时A1仅仅做为一个变量使用,没法做为类型来使用的。
// 是个坑 🥵 !
复制代码
children
类型定义例如src/component/Permission
组件的children
类型应该定义为children: React.ReactNode
。在 React 中将ReactNode
的类型定义成了:
type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;
复制代码
Form.create()
修饰器此修饰器目前在 ts 中没法使用,只能换成 function 的形式
例如:
@Form.create()
class Test{}
复制代码
换成:
class Test{}
Form.create()(Test)
复制代码
异常信息:
Property 'store' is missing in type '{}' but required in type 'Readonly<RcBaseFormProps & Pick<IProps, "store">>'.
复制代码
Search.tsx
源码:
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)
复制代码
第一种解决方法:
去掉constructor
中对 store 引用的定义。在IProps
的store
后面加一个可选符问号
interface IProps {
store?: {
rollbackEdit: RollbackEditStore
}
form: WrappedFormUtils
}
复制代码
将方法中引用的this.store
都修改成const { rollbackEdit } = this.props.store!
第二种解决方法:
不修改Search.tsx
中的代码,只须要在调用它的index.tsx
中将 store 给它传入进去便可:
const store = {
rollbackEdit,
}
const RollbackEdit = () => (
<Card title={ <CardTitle> <Search store={store} /> </CardTitle> } bordered={false} > <List /> </Card> ) 复制代码
与ts官网等,得知tsconfig的
module: 'commonjs'
复制代码
必然会致使代码分割实效,必须配置为
module: 'esnext'
复制代码
而webpack.config.ts
中又使用了commonjs的包,ts文档中明确说明,使用
export = xxxx
复制代码
导出的包,必须使用
import xxx = require('xxx')
复制代码
的方式来引入。但只要有这种包的使用,就没法使用esnext
的模块类型。
可选方案:
tsconfig-paths-webpack-plugin
,引入另外一个tsconfig.json
文件,该文件使用esnext
的模块方式。webpack
的ts-loader
中添加options
项,来达到使前端编译环境与源码环境使用不一样tsconfig配置的目的。options: {
compilerOptions: {
module: 'esnext',
},
},
复制代码
具体可查看:函数类型的双变性
interface Bird {
fly();
layEggs();
}
interface Fish {
swim();
layEggs();
}
function getSmallPet(): Fish | Bird {
// ...
}
let pet = getSmallPet();
// 每个成员访问都会报错
if (pet.swim) {
pet.swim();
}
else if (pet.fly) {
pet.fly();
}
复制代码
为了让这段代码工做,咱们须要使用类型断言:
let pet = getSmallPet();
if ((<Fish>pet).swim) {
(<Fish>pet).swim();
}
else {
(<Bird>pet).fly();
}
复制代码
这里能够注意到咱们不得很少次使用类型断言。 倘若咱们一旦检查过类型,就能在以后的每一个分支里清楚地知道pet
的类型的话就行了。 TypeScript里的类型守卫机制让它成为了现实。 类型守卫就是一些表达式,它们会在运行时检查以确保在某个做用域里的类型。 要定义一个类型守卫,咱们只要简单地定义一个函数,它的返回值是一个类型谓词:
function isFish(pet: Fish | Bird): pet is Fish {
return (<Fish>pet).swim !== undefined; } 复制代码
在这个例子里,pet is Fish
就是类型谓词。 谓词为parameterName is Type这种形式,parameterName必须是来自于当前函数签名里的一个参数名。 每当使用一些变量调用isFish
时,TypeScript会将变量缩减为那个具体的类型,只要这个类型与变量的原始类型是兼容的。
// 'swim' 和 'fly' 调用都没有问题了
if (isFish(pet)) {
pet.swim();
}
else {
pet.fly();
}
复制代码
一开始绕了弯路,用typescript-plugin-css-modules
,对less支持很差,当使用复杂less函数时会失效,在更新less文件时还常常须要重启tsserver。 后来改进参考以下: typings-for-css-modules-loader
使用一个webpack loader
,即时生成对应的.d.ts
文件来映射css modules
的class
。
只编译一个文件时,若是指定了tsc
参数,则不会自动加载当前项目的tsconfig.json
。这一点很迷惑,会生成错误的编译结果。
ts-loader
与fork-ts-checker-webpack-plugin
与awesome-typescript-loader
。ts-loader
单独使用,无命令行类型校验提示,且项目越多编译越慢。 ts-loader
须要与fork-ts-checker-webpack-plugin
一块儿使用,能够作到文件更新后秒编译,在命令行显示类型校验,但消耗内存多。 awesome-typescript-loader
消耗内存稍少,文件更新时编译快,且能够显示命令行类型校验。例如更改的是依赖较多的文件例如被view依赖的更底层的store,编译速度会稍微慢。
typescript
与preact
与web component
。首先须要在tsconfig.json中添加
"jsx": "react",
"jsxFactory": "h",
复制代码
在preact中使用自定义dom时,须要扩展IntrinsicElements,google上能搜到的地方都让扩展global下的JSX
declare namespace JSX {
interface IntrinsicElements {
foo: any
}
}
复制代码
但在preact
环境下JSX所在的命名空间不一样
declare global {
namespace preact {
namespace h {
namespace JSX {
interface IntrinsicElements {
'custom-node': any
}
}
}
}
}
复制代码
tsconfig.json
的路径别名path
若是只是当前项目使用,能够尽情用
在和其余项目一块儿使用时,个人状况是做为多包的lerna项目,一个包须要引入另外一个包的ts文件,则原包中的路径别名在另外一个包中是不能工做的。
.d.ts
与发布项目发布时,即便打开了tsconfig.json
中的declaration
,其中的.d.ts
文件也不会自动编译到outDir
指定的目录中去
若是项目中有定义须要依赖这些.d.ts
,须要在发布过程当中添加额外的复制脚本
.d.ts
中尽可能不要使用import
引入其余依赖,尤为是不能引入非纯定义文件的类型,好比该文件中含有实际的逻辑代码,不然发布后在使用该包的环境中不能正常工做
因为项目中有不少使用abstract定义的抽象类,在ts-loader编译时抽象类只做为类型检查使用。但使用babel编译时抽象类会生成真实的类,而且其中的属性也都会与类一块儿生成。在使用mobx扩展属性时形成冲突致使没法运行。