TypeScript-数组的约束

TypeScript-数组的约束,typescript,generics,types,typescript-typings,static-typing,Typescript,Generics,Types,Typescript Typings,Static Typing,我有以下(示例-)数组: 使用(示例-)接口 需要此数组类型的函数必须确保所有函数结果的统一实现完整接口。可能吗? 目前,我有: type Fn<Values> = (part: string) => { [key in keyof Values]?: string } type Item<Values> = string | Fn<Values>; function extract<Values>(items: Item<Value

我有以下(示例-)数组:

使用(示例-)接口

需要此数组类型的函数必须确保所有函数结果的统一实现完整接口。可能吗? 目前,我有:

type Fn<Values> = (part: string) => { [key in keyof Values]?: string }
type Item<Values> = string | Fn<Values>;

function extract<Values>(items: Item<Values>[]) {
  const values = {} as Values;
  // (...)
  return values;
}
type Fn=(part:string)=>{[key-in-keyof-Values]?:string}
类型项=字符串| Fn;
函数提取(项:项[]){
常量值={}作为值;
// (...)
返回值;
}
但是,此类型仅检查所有函数是否返回与
值的键匹配的对象,而不是检查所有键是否最终都存在


我不太确定TypeScript是否可以执行此检查,我发现它也用于类型的“计算”,但我不确定这是否适用于此用例。

我非常确信,您无法编写任何类型,其成员是所需形式的数组。如果让TypeScript将数组的元素类型推断为其成员类型的并集,则可以验证元素类型是否覆盖了整个接口:

interface MyValues { foo: string; bar: string; }

// From jcalz, https://stackoverflow.com/a/50375286
type UnionToIntersection<U> = 
  (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never

type Fn<Values> = (part: string) => { [key in keyof Values]?: string }
type Item<Values> = string | Fn<Values>;
type CheckComplete<Values, T extends Item<Values>> =
  // note: ReturnType is distributive.
  UnionToIntersection<ReturnType<Exclude<T, string>>> extends
  { [key in keyof Values]: string } ? unknown : never;

function extractFactory<Values>() {
  return function<T extends Item<Values>>(items: T[] & CheckComplete<Values, T>) {
    const values = {} as Values;
    // (...)
    return values;  
  };
}

const extract = extractFactory<MyValues>();

const a = [
  'test-string', 
  foo => ({ foo }), 
  'other-string', 
  bar => ({ bar })
];
extract(a);  // OK

const b = [
  'test-string', 
  foo => ({ foo }), 
  'other-string'
];
extract(b);  // Error
接口MyValues{foo:string;bar:string;}
//来自jcalz,https://stackoverflow.com/a/50375286
类型UnionToIntersection=
(U扩展任何?(k:U)=>void:never)扩展((k:inferi)=>void)?I:从来没有
类型Fn=(部分:字符串)=>{[key-in-keyof-Values]?:string}
类型项=字符串| Fn;
类型检查完成=
//注意:ReturnType是分布式的。
UnionToIntersection扩展
{[key-in-keyof-Values]:string}?未知:从未;
函数提取工厂(){
返回函数(项:T[]和CheckComplete){
常量值={}作为值;
// (...)
返回值;
};
}
const extract=extractFactory();
常数a=[
“测试字符串”,
foo=>({foo}),
“其他字符串”,
bar=>({bar})
];
摘录(a);//好啊
常数b=[
“测试字符串”,
foo=>({foo}),
“其他字符串”
];
摘录(b);//错误
但是,通过将图元类型设置为并集的注释可以轻松绕过该检查,但并非其所有成员都实际出现在数组中:

extract<string
  | ((arg: string) => {foo: string})
  | ((arg: string) => {bar: string})>(b);  // Wrong but no error
extract{foo:string})
|((arg:string)=>{bar:string})>(b);//错但没有错

如果一个数组中始终有4个项,则可以使用元组,该数组可以是任意长度的。接口也可以有任何形式。
interface MyValues { foo: string; bar: string; }

// From jcalz, https://stackoverflow.com/a/50375286
type UnionToIntersection<U> = 
  (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never

type Fn<Values> = (part: string) => { [key in keyof Values]?: string }
type Item<Values> = string | Fn<Values>;
type CheckComplete<Values, T extends Item<Values>> =
  // note: ReturnType is distributive.
  UnionToIntersection<ReturnType<Exclude<T, string>>> extends
  { [key in keyof Values]: string } ? unknown : never;

function extractFactory<Values>() {
  return function<T extends Item<Values>>(items: T[] & CheckComplete<Values, T>) {
    const values = {} as Values;
    // (...)
    return values;  
  };
}

const extract = extractFactory<MyValues>();

const a = [
  'test-string', 
  foo => ({ foo }), 
  'other-string', 
  bar => ({ bar })
];
extract(a);  // OK

const b = [
  'test-string', 
  foo => ({ foo }), 
  'other-string'
];
extract(b);  // Error
extract<string
  | ((arg: string) => {foo: string})
  | ((arg: string) => {bar: string})>(b);  // Wrong but no error