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擴展屬性時形成衝突致使沒法運行。