Skip to content

Instantly share code, notes, and snippets.

@idhowardgj94
Last active June 17, 2020 02:52
Show Gist options
  • Save idhowardgj94/b4394360ab6cd56f472bfdd8588d9fa5 to your computer and use it in GitHub Desktop.
Save idhowardgj94/b4394360ab6cd56f472bfdd8588d9fa5 to your computer and use it in GitHub Desktop.
reply
function 有分 declare 跟 invoke 對吧
type 也有
對 term level 來講 type 不管是 declare 還是 invoke ,都是宣告

我大概理解這個問題了。我會有這樣錯誤的觀念,是我之前在寫 ts 版本的 redux saga的時候,遇到這個問題。

redux-saga/redux-saga#1883

當時我的解決方式,是將 takeLatest 加上 any, error訊息就消失了。

function * loginHandler({ payload }: { payload: LoginRequest }) {
 // do something ....
}

export default function * () {
    yield takeLatest<any>(LOGIN, loginHandler);
}

如果takeLatest不加 any的話,會報 issues上的error:

Argument of type '"LOGIN"' is not assignable to parameter of type 'TakeableChannel<unknown>'.

當時一直認為是因為 takeLatest 有標 generic type。所以在使用時一定要給它一個型態。

你跟我提到 type variable的概念以後,我覺得一定有地方有問題,所以再試著去理解一次。

我認為這裡的問題應該是,因為我在 loginHandler function 時,使用解構賦值,直接從 Action object 中取出 payload

並只標出 payload 的型態。

而在 redux saga 的實作中,會找 action 中的 type 屬性,並將它的型態賦與TakeableChannel<T> 的 T:

// 一個 action。
interface Action {
  type: string; // <- 這一個type 會是 TakeableChannel<T> 的 <T>
  payload: any;
}

// .... (some code)

// 這裡只取出 payload,因此 takeableChannel取 type 的 型態的時候,會是 `unknown`
function * loginHandler({ payload }: { payload: LoginRequest }) {
  // do something
}

這裡還有一個我沒有注意到的特性,就是takeLatest 的 type variable 可以是 literal string。

這是不是代表typescript中的 type variable 可以是一個抽象的型態?

// LOGIN 是我定義的 const string。
// takeLatest(LOGIN, loginHandler) 的 type hint: 
// takeLatest<"LOGIN">(pattern: "LOGIN", worker: (action: Action<any>) => any): ForkEffect<never> 

所以其實真正的問題並不是 takeLatest一定要加上 generic type。

而是因為在lib function 堆疊的過程中,lost 掉了某個 generic type,所以才會報錯。

照著 issue 上的回覆改一下 code,就不會報錯了。

function * loginHandler({ type, payload }: { type: typeof LOGIN, payload: LoginRequest }) {
   // ..........
}
// ....
export default function * () {
 yield takeLatest(LOGIN, loginHandler);
}

這又是一個我自以為我懂了的經典案例……

弄懂了這個關係以後,我更理解了 type variable ( generic type)的觀念;

修正觀念後,對我標 type signature應該是有幫助的。

還有你不斷提到的 generic type 跟 haskell 的 type variable其實只有語法上的不同,這樣應該也算真的理解了。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment