如何使用typeof获取对象的“运行时”类型?

问题描述 投票:0回答:2

我想获得已经声明的键/值的对象类型。我有以下代码:

interface ConfigVar<T extends 'string' | 'number' | 'boolean'> {
  env: string;
  type: T;
}

interface ConfigMap {
  [key: string]: ConfigVar<'string'> | ConfigVar<'number'> | ConfigVar<'boolean'>;
}

type ConfigType<T extends ConfigMap> = {
  [P in Extract<keyof T, string>]:
    T[P] extends ConfigVar<'string'> ? string :
    T[P] extends ConfigVar<'boolean'> ? boolean :
    T[P] extends ConfigVar<'number'> ? number :
    never;
};

// usage

const configMap: ConfigMap = {
  var1: {
    env: 'VAR1',
    type: 'string',
  },
};

type ConfigMapType = ConfigType<typeof configMap>;

const config: ConfigMapType = {
  var1: true, // Type 'boolean' is not assignable to type 'never'
  // var1: 'str', // Type 'string' is not assignable to type 'never'
};

我的目标是使ConfigMapType只允许{ var1: string }。打字稿有可能吗?

typescript
2个回答
1
投票

您的条件类型没问题,唯一的问题是保留configMap的实际类型。如果您有一个显式类型注释,它将是变量的最终类型,并且对象文字的类型将不会发挥作用。保持约束和从对象文字中推断类型的最佳方法是使用泛型函数:

interface ConfigVar<T extends 'string' | 'number' | 'boolean'> {
  env: string;
  type: T;
}

interface ConfigMap {
  [key: string]: ConfigVar<'string'> | ConfigVar<'number'> | ConfigVar<'boolean'>;
}

type ConfigType<T extends ConfigMap> = {
  [P in Extract<keyof T, string>]:
    T[P] extends ConfigVar<'string'> ? string :
    T[P] extends ConfigVar<'boolean'> ? boolean :
    T[P] extends ConfigVar<'number'> ? number :
    never;
};

// usage

const configMap = (<T extends ConfigMap>(o:T)=> o)({
  var1: {
    env: 'VAR1',
    type: 'string',
  },
});

type ConfigMapType = ConfigType<typeof configMap>;

const config: ConfigMapType = {

  var1: 'str
};

1
投票

configMapvar1都是值,而不是类型。因此,TypeScript无法验证它。您需要将var1放在其中一个类型定义中,例如:

type ConfigMapType = ConfigType<{ var1: ConfigVar<'string'> }>;

要么

interface ConfigVar<T extends 'string' | 'number' | 'boolean' = 'string'> {
    env: string;
    type: T;
}

type ConfigType<T> = {
    [P in Extract<keyof T, string>]:
    T[P] extends ConfigVar<'string'> ? string :
    T[P] extends ConfigVar<'boolean'> ? boolean :
    T[P] extends ConfigVar<'number'> ? number :
    never;
};

const configMap = {
    var1: <ConfigVar>{
        env: 'VAR1',
        type: 'string',
    },
};

type ConfigMapType = ConfigType<typeof configMap>;

const config: ConfigMapType = {
    var1: 'string',
};
© www.soinside.com 2019 - 2024. All rights reserved.