我是 TypeScript 的新手,正在嘗試將現有的 JS (react) 專案慢慢遷移到 TypeScript。
我有一個執行查詢的函式:
/**
* Run a Query against the currently connected database
* @param {String} sql Query to run
* @param {Object[]} Array of objects to be used in the prepared statement
* @returns {Promise<Object[]>} Promise resolving after query is done. Returns an array of arrays with the result.
*/
const query = (sql, params) => {
//Database stuff
}
我在很多地方都這樣稱呼它:
const result = await query('SELECT count(*) as cnt from Table id=?',[2]')
return result[0].cnt
最后一行給出了錯誤,因為欄位“cnt”是未知的。如何最好地解決這個問題?回傳型別始終為 Object[],但物件的內容 ob 取決于查詢。
任何建議如何最好地將此代碼移動到 TS?
uj5u.com熱心網友回復:
這是型別系統必須被告知您期望什么的地方之一。自然,在這樣做時您必須非常小心,以確保您為型別系統提供準確的資訊。通常,您希望盡可能早地執行此操作,以便在其上構建的更復雜的代碼可以依賴于型別。
所以分兩部分回答:
如何打字
query,以及避免
query直接使用的建議
首先,您可以query通過給它一個泛型型別引數來告訴它它回傳什么型別的物件來創建一個泛型函式:
/**
* Run a Query against the currently connected database
* @param {string} sql Query to run
* @param {any[]} Array of objects to be used in the prepared statement
* @returns {Promise<ResultType[]>} Promise resolving after query is done. Returns an array of arrays with the result.
*/
const query = <ResultType extends object>(sql: string, params: any[]): Promise<ResultType[]> => {
// ???????????^^^^^^^^^^^^^^^^^^^^^^^^^^^??????????????????????????????^^^^^^^^^^^^^^^^^^^^^
//Database stuff
};
然后例如你可以像這樣使用它:
const result = await query<{cnt: number}>('SELECT count(*) as cnt from Table id=?', [2]);
// ????????????????????????^^^^^^^^^^^^^
return result[0].cnt;
但這是#2的用武之地:我不會這樣做,除非在您定義一次的函式中,它的作業是告訴您有多少行匹配:
async function getCountFromExampleTable(id: number): Promise<number> {
const result = await query<{cnt: number}>('SELECT count(*) as cnt from Table id=?', [id]);
return result[0].cnt;
}
很容易查看getCountFromExampleTable并知道我們給出的型別引數 ( {cnt: number}) 是正確的。然后任何需要執行此操作的代碼都可以重用getCountFromExampleTable,而不必提供該型別引數(并且可能會出錯)。
您可能想要getCountFromExampleTable更通用,也許接受表名和引數,但您明白了。(如果是這樣,請務必測驗表名以確保它不能用作 SQL 注入攻擊的一部分,并繼續使用您已經準備好的陳述句。)
游樂場鏈接
uj5u.com熱心網友回復:
您可能應該使用泛型告訴您“資料庫的東西”它可以期望什么樣的回傳型別:
const query = function <T>(sql:string, params:object):Array<T> {
//Database stuff that probably has an overload that accepts `<T>`
}
// Or:
const query = <T,>(sql:string, params:object):Array<T> => {
//Database stuff that probably has an overload that accepts `<T>`
}
像這樣呼叫:
await query<MyDataRow>('SELECT ...');
uj5u.com熱心網友回復:
你必須使用泛型
const query = <T>(sql: string, params: Object[]): T[] => {
return []
}
但是函式可以回傳空陣列。在這種情況下,您可以像這樣檢查cnt屬性
const result = await query('SELECT count(*) as cnt from Table id=?',[2])
return result[0]?.cnt
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/494337.html
標籤:javascript 打字稿
