如何从TypeScript中的对象数组创建类型?

如何从TypeScript中的对象数组创建类型?,typescript,union-types,Typescript,Union Types,给定一个国家数组,如下所示: const国家=[ {名称:“澳大利亚”,代码:“AU”}, {名称:“日本”,代码:“JP”}, {名称:“挪威”,代码:“否”}, {名称:“俄罗斯联邦”,代码:“RU”} ]; 生成以下类型的最简单方法是什么 键入CountryCodes=”“|“AU”|“JP”|“NO”|“RU”; 注意:有一个额外的空字符串。尽管从JS的角度来看,该函数是无用的。它能够将代码统一为一种类型 function createCountries<T extends s

给定一个
国家
数组,如下所示:

const国家=[
{名称:“澳大利亚”,代码:“AU”},
{名称:“日本”,代码:“JP”},
{名称:“挪威”,代码:“否”},
{名称:“俄罗斯联邦”,代码:“RU”}
];
生成以下类型的最简单方法是什么

键入CountryCodes=”“|“AU”|“JP”|“NO”|“RU”;

注意:有一个额外的空字符串。

尽管从JS的角度来看,该函数是无用的。它能够将代码统一为一种类型

function createCountries<T extends string>(
  contries: { name: string; code: T }[],
): { name: string; code: T }[] {
  return contries;
}

const countries = createCountries([
  { name: "Australia", code: "AU" },
  { name: "Japan", code: "JP" },
  { name: "Norway", code: "NO" },
  { name: "Russian Federation", code: "RU" }
]);

type CountryCodes = "" | (typeof countries)[number]["code"]; // "" | "AU" | "JP" | "NO" | "RU";

// Example - How to use the type
function getCountryByCode(code: CountryCode): Country | undefined {
  return countries.find(country => country.code == code);
}

没有进一步的信息,这是你能做的最好的

type Countries = { name: string; code: string }[];

const countriesAbc = [
  { name: "Australia", code: "AU" },
  { name: "Japan", code: "JP" },
  { name: "Norway", code: "NO" },
  { name: "Russian Federation", code: "RU" }
] as const;

const countries: Countries = [...countriesAbc];

type CountryCodes = "" | (typeof countriesAbc)[number]["code"]; // "" | "AU" | "JP" | "NO" | "RU";

虽然从JS的角度来看,该函数是无用的。它能够将代码统一为一种类型

function createCountries<T extends string>(
  contries: { name: string; code: T }[],
): { name: string; code: T }[] {
  return contries;
}

const countries = createCountries([
  { name: "Australia", code: "AU" },
  { name: "Japan", code: "JP" },
  { name: "Norway", code: "NO" },
  { name: "Russian Federation", code: "RU" }
]);

type CountryCodes = "" | (typeof countries)[number]["code"]; // "" | "AU" | "JP" | "NO" | "RU";

// Example - How to use the type
function getCountryByCode(code: CountryCode): Country | undefined {
  return countries.find(country => country.code == code);
}

没有进一步的信息,这是你能做的最好的

type Countries = { name: string; code: string }[];

const countriesAbc = [
  { name: "Australia", code: "AU" },
  { name: "Japan", code: "JP" },
  { name: "Norway", code: "NO" },
  { name: "Russian Federation", code: "RU" }
] as const;

const countries: Countries = [...countriesAbc];

type CountryCodes = "" | (typeof countriesAbc)[number]["code"]; // "" | "AU" | "JP" | "NO" | "RU";

你可以用另一种方式做

type CountryCodes = "" | "AU" | "JP" | "NO" | "RU";

interface Country {name: string; code: CountryCodes} 
// Alternatively
// type Country = {name: string; code: CountryCodes}


const countries: Array<Country> = [ 
  { name: "Australia", code: "DE" }, // COMPILE ERROR
  { name: "Japan", code: "JP" },
  { name: "Norway", code: "NO" },
  { name: "Russian Federation", code: "RU" }
];
键入CountryCodes=”“|“AU”|“JP”|“NO”|“RU”;
接口国家{名称:字符串;代码:CountryCodes}
//或者
//键入Country={name:string;code:CountryCodes}
常量国家/地区:数组=[
{name:“Australia”,代码:“DE”},//编译错误
{名称:“日本”,代码:“JP”},
{名称:“挪威”,代码:“否”},
{名称:“俄罗斯联邦”,代码:“RU”}
];
甚至更好

type NotEmptyCountryCodes = "AU" | "JP" | "NO" | "RU";

type CountryCodes = "" | NotEmptyCountryCodes;

interface Country {name: string; code: NotEmptyCountryCodes}
// Alternatively
// type Country = {name: string; code: NotEmptyCountryCodes}

const countries: Array<Country> = [ 
  { name: "Australia", code: "DE" }, // COMPILE ERROR
  { name: "Japan", code: "" }, // COMPILE ERROR
  { name: "Norway", code: "NO" },
  { name: "Russian Federation", code: "RU" }
];
键入notemptycountrycode=“AU”|“JP”|“NO”|“RU”;
键入CountryCodes=“”| NotEmptyCountryCodes;
接口国家{名称:字符串;代码:NotEmptyCountryCodes}
//或者
//键入Country={name:string;code:notemptycountrycode}
常量国家/地区:数组=[
{name:“Australia”,代码:“DE”},//编译错误
{name:“Japan”,代码:},//编译错误
{名称:“挪威”,代码:“否”},
{名称:“俄罗斯联邦”,代码:“RU”}
];

你可以用另一种方式做

type CountryCodes = "" | "AU" | "JP" | "NO" | "RU";

interface Country {name: string; code: CountryCodes} 
// Alternatively
// type Country = {name: string; code: CountryCodes}


const countries: Array<Country> = [ 
  { name: "Australia", code: "DE" }, // COMPILE ERROR
  { name: "Japan", code: "JP" },
  { name: "Norway", code: "NO" },
  { name: "Russian Federation", code: "RU" }
];
键入CountryCodes=”“|“AU”|“JP”|“NO”|“RU”;
接口国家{名称:字符串;代码:CountryCodes}
//或者
//键入Country={name:string;code:CountryCodes}
常量国家/地区:数组=[
{name:“Australia”,代码:“DE”},//编译错误
{名称:“日本”,代码:“JP”},
{名称:“挪威”,代码:“否”},
{名称:“俄罗斯联邦”,代码:“RU”}
];
甚至更好

type NotEmptyCountryCodes = "AU" | "JP" | "NO" | "RU";

type CountryCodes = "" | NotEmptyCountryCodes;

interface Country {name: string; code: NotEmptyCountryCodes}
// Alternatively
// type Country = {name: string; code: NotEmptyCountryCodes}

const countries: Array<Country> = [ 
  { name: "Australia", code: "DE" }, // COMPILE ERROR
  { name: "Japan", code: "" }, // COMPILE ERROR
  { name: "Norway", code: "NO" },
  { name: "Russian Federation", code: "RU" }
];
键入notemptycountrycode=“AU”|“JP”|“NO”|“RU”;
键入CountryCodes=“”| NotEmptyCountryCodes;
接口国家{名称:字符串;代码:NotEmptyCountryCodes}
//或者
//键入Country={name:string;code:notemptycountrycode}
常量国家/地区:数组=[
{name:“Australia”,代码:“DE”},//编译错误
{name:“Japan”,代码:},//编译错误
{名称:“挪威”,代码:“否”},
{名称:“俄罗斯联邦”,代码:“RU”}
];

我认为,从域名的角度来看,它可能希望国家代码的更改更少,国家名称更灵活。若您的问题只是从map-like列表中生成联合字符串类型,那个么另一种方法更好

从常量列表中生成联合类型CountryCode(这在以下情况下很有用):

使用CountryCode定义国家/地区:

type Country = { name: string; code: CountryCode};
与in一起使用时,安全灵活:

// mock of date access.
const fetchByCode = (code: CountryCode, lang: string) : string => {
  return "name of " + code;
};

// create county data from code list.
const createCountries = () : Country[] => {
  return countryCodeList.map((code) => {
    const name = fetchByCode(code,'en');
    return {name, code}
  });
};

// use country data.
const countriesEn = createCountries()
console.log(countriesEn);

我认为,从域名的角度来看,它可能期望国家代码的变化更少,国家名称更灵活。若您的问题只是从map-like列表中生成联合字符串类型,那个么另一种方法更好

从常量列表中生成联合类型CountryCode(这在以下情况下很有用):

使用CountryCode定义国家/地区:

type Country = { name: string; code: CountryCode};
与in一起使用时,安全灵活:

// mock of date access.
const fetchByCode = (code: CountryCode, lang: string) : string => {
  return "name of " + code;
};

// create county data from code list.
const createCountries = () : Country[] => {
  return countryCodeList.map((code) => {
    const name = fetchByCode(code,'en');
    return {name, code}
  });
};

// use country data.
const countriesEn = createCountries()
console.log(countriesEn);

首先,如果不稍微修改输入数据集类型,就无法实现所需的功能。正如所正确指出的,这里的数组成员类型被扩展为
{name:string;code:string;}
。这可以通过断言轻松解决:

const国家=[
{名称:“澳大利亚”,代码:“AU”},
{名称:“日本”,代码:“JP”},
{名称:“挪威”,代码:“否”},
{名称:“俄罗斯联邦”,代码:“RU”}
]作为常量;
现在数组本身被视为一个元组,每个成员的属性也被设置为只读。之后,您只需要一个映射类型来提取元组的值(通常使用
T[number]
),获取
code
成员的类型,并从中构建联合:

type CountryCodes={
[P in keyof T]:T[P]扩展{code:string}?T[P][“code”]:从不
}[keyof T&number]|“;
其中
T[p]扩展了{code:string}
约束确保我们可以用
的“code”
索引
T[p]
。结果正是您想要的(请注意,一切都是在类型系统中完成的):

类型cc=国家代码//键入cc=”“|“AU”|“JP”|“NO”|“RU”


更简洁的版本利用了4.1的功能:

type CountryCodes=keyof{
[P作为T[P]扩展{code:string}?T[P][“code”]:never]:T[P]
} | "";

首先,如果不稍微修改输入数据集类型,就无法实现所需的功能。正如所正确指出的,这里的数组成员类型被扩展为
{name:string;code:string;}
。这可以通过断言轻松解决:

const国家=[
{名称:“澳大利亚”,代码:“AU”},
{名称:“日本”,代码:“JP”},
{名称:“挪威”,代码:“否”},
{名称:“俄罗斯联邦”,代码:“RU”}
]作为常量;
现在数组本身被视为一个元组,每个成员的属性也被设置为只读。之后,您只需要一个映射类型来提取元组的值(通常使用
T[number]
),获取
code
成员的类型,并从中构建联合:

type CountryCodes={
[P in keyof T]:T[P]扩展{code:string}?T[P][“code”]:从不
}[keyof T&number]|“;
其中
T[p]扩展了{code:string}
约束确保我们可以用
的“code”
索引
T[p]
。结果正是您想要的(请注意,一切都是在类型系统中完成的):