網站搜尋

使用 TypeScript 更新物件屬性


我正在嘗試從一個物件動態更新一個帶有選項屬性的物件。在代碼中,我遇到了一個錯誤,錯誤顯示 axiosOptions.headers[key](我在下面的代碼示例中留下了註解)。

TypeScript 錯誤

Type 'string | undefined' is not assignable to type '"true" | "false"'.
  Type 'undefined' is not assignable to type '"true" | "false"'.

我的程式碼

type ApiHeaders = {
  Accept: string;
  'Content-Type': string;
  IsRequireAdmin: 'true' | 'false';
  Authorization?: string;
  BarCode?: string;
  DomainName?: string;
};

interface AxiosOptions {
  params?: any;
  data?: any;
  headers: ApiHeaders;
}

const axiosOptions: AxiosOptions = {
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
    IsRequireAdmin: 'false'
  }
};

const updateAxiosOptionsHeaders = (newApiHeaders: Partial<ApiHeaders>): void => {
  let key: keyof Partial<ApiHeaders>;
  for (key in newApiHeaders) axiosOptions.headers[key] = newApiHeaders[key]; // <----------- typescript error
};

const token: string = 'my_token';
const barCode: string = 'my_bar_code';
const domainName: string = 'www.mydomain.com';

const newApiHeaders: Omit<ApiHeaders, 'Content-Type' | 'Accept'> = {
  'IsRequireAdmin': 'true',
  'Authorization': `Bearer ${token}`,
  'BarCode': barCode,
  'DomainName': `DATA\\${domainName}`
  };

updateAxiosOptionsHeaders(newApiHeaders);

我對如何解決這個問題持開放態度,願意聽取建議。

答案#1

TypeScript 不知道它不知道的東西。它不知道在任何一次執行 updateAxiosOptionsHeaders 時 key 會是什麼,所以它選擇了最嚴格的可能解釋。當然,有很多不同的方法可以解決這個問題,但如果你想保持類型不變,你可以在函數中這樣做來解決它:

type ApiHeaders = {
  Accept: string;
  'Content-Type': string;
  IsRequireAdmin: 'true' | 'false';
  Authorization?: string;
  BarCode?: string;
  DomainName?: string;
};

interface AxiosOptions {
  params?: any;
  data?: any;
  headers: ApiHeaders;
}

const axiosOptions: AxiosOptions = {
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
    IsRequireAdmin: 'false'
  }
};

const updateAxiosOptionsHeaders = (newApiHeaders: Partial<ApiHeaders>): void => {
  let key: keyof Partial<ApiHeaders>;
  for (key in newApiHeaders) {
    if (key === 'IsRequireAdmin') {
        // Note the default value if one isn't provided in newApiHeaders for some reason
        axiosOptions.headers.IsRequireAdmin = newApiHeaders.IsRequireAdmin ?? 'false';
    } else {
        // ditto here
        axiosOptions.headers[key] = newApiHeaders[key] ?? '';
    } 
  }
};
const token: string = 'my_token';
const barCode: string = 'my_bar_code';
const domainName: string = 'www.mydomain.com';

const newApiHeaders: Partial<ApiHeaders> = {
  'IsRequireAdmin': 'true',
  'Authorization': `Bearer ${token}`,
  'BarCode': barCode,
  'DomainName': `DATA\\${domainName}`
  };

updateAxiosOptionsHeaders(newApiHeaders);

查看已更改部分的評論;你需要決定合理的預設值。

答案#2

你需要允許 undefined。這是在宣告類型時完成的,而不是在類型轉換時。見下文。

type ApiHeaders = {
  Accept: string;
  'Content-Type': string;
  IsRequireAdmin: 'true' | 'false' | undefined;
  Authorization?: string;
  BarCode?: string;
  DomainName?: string;
};