当接口中的所有键在打字稿中都是可选的时,提供的意外字段不报告错误

when all the key in interface is optional in typescript, an unexpected field provided is not report an error

当typescript中interface中的所有key都是optional时,提供一个意想不到的字段不报错,为什么?这是我的代码片段:

// This is an interface which all the key is optional
interface AxiosRequestConfig {
  url?: string;
  method?: string;
  baseURL?: string;
  headers?: any;
  params?: any;
  paramsSerializer?: (params: any) => string;
  data?: any;
  timeout?: number;
  timeoutErrorMessage?: string;
  withCredentials?: boolean;
  responseType?: ResponseType;
  xsrfCookieName?: string;
  xsrfHeaderName?: string;
  onUploadProgress?: (progressEvent: any) => void;
  onDownloadProgress?: (progressEvent: any) => void;
  maxContentLength?: number;
  validateStatus?: ((status: number) => boolean) | null;
  maxBodyLength?: number;
  maxRedirects?: number;
  socketPath?: string | null;
  httpAgent?: any;
  httpsAgent?: any;
}

“a”字段是意外的,为什么TypeScript不报错?

type test= {
  [key:string]: (...args:any[])=> AxiosRequestConfig
}

const serviceMap: test = { 
  getOperationLogListByConditions(conditions: any) {
    const { 
      currentPageIndex,
      createTimeStart,
      createTimeEnd,
      ...rest
    } = conditions

    return {
      url: '/operateLog/page',
      method: 'GET',
      params: {
        ...rest,
        pageNo: currentPageIndex,
        createTimeStart: encodeURIComponent(createTimeStart),
        createTimeEnd: encodeURIComponent(createTimeEnd)
      },
      a:"" // "a" field is unexpected, why TypeScript does not report an error ?
    }
  }

我不明白为什么,请帮忙!打字稿版本是4.1.2.

return 类型未触发“超额 属性 检查”。这就是excess字段a没有报错信息的原因。 AxiosRequestConfig 的所有属性都是可选的这一事实是无关紧要的 see playground

相比之下,对于赋值语句中的表达式和变量类型以及函数调用中的参数和参数类型,会触发“超出 属性 检查”。

interface Props1 {
  age: number;
}

// expression assignment: excess property check is triggered
let x: Props1 = {age: 1, test: "tutu"}; 

function returnProps1(): Props1 {
  let props = {age: 1, test: "tutu"};
  // return type: excess property check is NOT triggered
  return props
}

额外的 属性 检查也会在 “新鲜” 对象文字赋值时触发。在类型断言和类型扩展的情况下,对象文字的新鲜度消失了。在您的情况下,类型断言会丢失对象文字的新鲜度,因为您没有在函数定义中指定 returned 类型。

const serviceMap: test = { 
  getOperationLogListByConditions(conditions: any) {
    const { 
      currentPageIndex,
      createTimeStart,
      createTimeEnd,
      ...rest
    } = conditions
    
    // type assertion occurs here.
    // freshness of the object literal is lost
    // Excess property chek is not triggered
    return {
      url: '/operateLog/page',
      method: 'GET',
      params: {
        ...rest,
        pageNo: currentPageIndex,
        createTimeStart: encodeURIComponent(createTimeStart),
        createTimeEnd: encodeURIComponent(createTimeEnd)
      },
      a:"" // "a" field is unexpected, why TypeScript does not report an error ?
    }
  }

一种解决方案是在函数定义中指定 return 类型以保持对象文字的新鲜度。

const serviceMap: Test = { 
  getOperationLogListByConditions(conditions: any): 
  AxiosRequestConfig {
    const { 
      currentPageIndex,
      createTimeStart,
      createTimeEnd,
      ...rest
    } = conditions

    // No type assertion
    // object literal is fresh
    // excess property check is triggered
    return {
      url: '/operateLog/page',
      method: 'GET',
      params: {
        ...rest,
        pageNo: currentPageIndex,
        createTimeStart: encodeURIComponent(createTimeStart),
        createTimeEnd: encodeURIComponent(createTimeEnd)
      },
      a:"" // Error message
    }
  }
}

see playground