簡體   English   中英

是否可以檢測 TypeScript 中的泛型類型?

[英]Is it possible to detect type of generic in TypeScript?

我正在嘗試使用 generics 以便調用者可以定義他們預測得到的類型。

我的代碼是這樣的:

const getStoredData = async <T extends string | object>(key: typeof localStorageKeys[number]): Promise<T | null> => {
  try {
    // value is always returned as string
    const value = await AsyncStorage.getItem(key);

    if (value === null) return null;

    // I want to create condition to check if T is string or not
    // if T is object type then return parsed JSON, otherwise just string
    return value != null ? JSON.parse(value) : null;

  } catch (e) {
    return null;
  }
};

// I wanna achieve like below using the function above
// storedValue should be string
const storedValue = await getStoredValue<string>('someKey');

// then storedObjValue should be MyCustomType type
const storedObjValue = await getStoredValue<MyCustomType>('some_key');

有誰知道如何實現這一目標?

我會使用try/catch 塊

let returnValue;
try {
    returnValue = JSON.parse(value);
} catch(e) {
    returnValue = value;
}

如果JSON.parse失敗,它會將其設置為字符串值。

原答案:

您可以使用typeof

typeof value === 'string' ? value : JSON.parse(value)

為了回答這些問題,我想到了 ts 編譯器如何在運行代碼之前知道這些數據。 如果項目已經從類型定義中獲得了該數據,那么您可以從中推斷出它,但如果數據是通過請求來自外部源,則 ts 編譯器無法推斷出它將是什么。

但是您仍然可以做一些事情,那就是創建您自己的 AsyncStorage 期望定義。 所以我建議你創建一個接口來定義鍵和預期的結果。

interface DataSource {
  someKey: number;
  some_key: string;
  Some_Key: Record<string, number>;
}

const dataSource: DataSource = {
  someKey: 1,
  some_key: "a",
  Some_Key: {
    value: 2,
  },
};

interface AsyncStorage {
  get: <T extends keyof DataSource>(key: T) => DataSource[T];
}

const storage: AsyncStorage = {
  get: (key) => dataSource[key],
};

const key1 = storage.get("someKey"); // string
const key2 = storage.get("some_key"); // number
const key3 = storage.get("Some_Key"); // Record<string, number>

聽取@Gonzalo 的建議,我按照下面的方式進行操作,並且似乎有效。

type LocalStorageType = {
  user_id: string;
  user_something: UserSomethingType;
};
type LocalStorageKeys = keyof LocalStorageType;
type LocalStorageValue = LocalStorageType[LocalStorageKeys];

const getStoredData = async <T extends LocalStorageValue>(
  key: LocalStorageKeys,
): Promise<T | null> => {
  try {
    const value = await AsyncStorage.getItem(key);

    if (value === null) return null;

    if (key === 'user_id') return value as T;

    return JSON.parse(value) as T;
  } catch (e) {
    return null;
  }
};

這可能不是最佳的,因為 LocalStorageType 中可能的字符串值可能會增加很多if如下所示。

type LocalStorageType = {
   user_id: string;
   user_name: string;
   user_email: string;
   user_something: UserSomethingType;
   some_value: CustomType;
   some_value_two: CustomOneType;
};
// now I have to make at least 3 conditions(user_id, user_name, user_email) to distinguish string or custom types

如果有人知道如何防止這種情況,請告訴我!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM