如何在Typescript查找中匹配键和值。

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

更新:感谢@OliverRadini把我带到那里。

感谢@OliverRadini帮我找到了答案。根据他们的回答,我有一个在我的情况下可行的解决方案。我对他们的回答唯一的问题是,我需要从外部输入你要传递到函数中的内容,但我想不出一种方法可以在不在函数中推断出密钥。在我的情况下,用一个util来帮我们完成这个任务就可以了,如下图。

interface ITest {
  n: number;
  b: boolean;
}

const f = <K extends keyof ITest>(x: { id: K; params: ITest[K] }) => ({
  ...x,
  _propToConfirmYourUsingTheUtilNeverWriteThisManually: true,
});

type Props = ReturnType<typeof f>;

const a: Props = f({ id: "n", params: 1 }); // no type error
const b: Props = f({ id: "n", params: true }); // Type 'true' is not assignable to type 'number'

const c = f({ id: "b", params: true }); // no type error
const d = f({ id: "b", params: 1 }); // Type 'number' is not assignable to type 'boolean'

// Errors because we didn't add _propToConfirmYourUsingTheUtilNeverWriteThisManually
// This ridiculously named prop should ensure we don't override it without noticing
const z: Props = {
  // Property '_propToConfirmYourUsingTheUtilNeverWriteThisManually' is missing in type ...
  id: "b",
  params: 7,
};

f(a); // no type error
f(b); // no type error
f(c); // no type error
f(d); // no type error


UPDATE:

这种情况可以通过。

const invalidProps1: Props<IdsWithParameters> = {
  id: "id1",
  params: {
    param1: "string",
  },
};

额外的属性在这之外的代码中是没有问题的。但是要想让这个组件函数能够通用,并且能够取任何id中的 IdsWithParameters 我们不能像这样明确地指定密钥。Props<'id1'> 如 @oliverradini 的回答。但他们的帮助让我找到了这个接近但仍不尽如人意的东西。

interface Props<K extends keyof IdsWithParameters> {
  id: K;
  params: IdsWithParameters[K];
}

// Somehow want Props to know what is being used as the id and infer 
// the correct params type
function Text(props: Props) {
  const text = intlFunctionThatGetsTheTranslatedText(props.id, props.params);

  return <>{text}</>
}


原帖。

我正在构建一个库,在这个库中,我需要允许人们创建一个对象(IdsWithParameters接口),指定允许的键和允许与每个特定键一起使用的类型参数。在不同的地方,他们会希望指定一个对象,该对象具有和。idparams Props接口),从IdsWithParameters实例中匹配1个特定的键值对。

我可以通过查找达到一个点,即你必须向 Props 实例传递一个有效的 key 和 params。但不知道如何将params限制为与给定keyid匹配的那些。

interface IdsWithParameters {
  id1: {};
  id2: {
    param1: string;
  };
  id3: {
    param2: boolean;
    param3: number;
  };
}

interface Props<I extends IdsWithParameters> {
  id: keyof I;
  params: I[keyof I];
}

// This works as expected
const validProps1: Props<IdsWithParameters> = {
  id: "id1",
  params: {},
};

// This works as expected
const validProps2: Props<IdsWithParameters> = {
  id: "id2",
  params: {
    param1: "string",
  },
};

const invalidProps1: Props<IdsWithParameters> = {
  id: "id1",
  // Want this to error, saying that params should be {} but it passes
  params: {
    param1: "string",
  },
};

const invalidProps2: Props<IdsWithParameters> = {
  id: "id2",
  // Want this to error, saying that params should be { param1: string; } but it passes
  params: {},
};

我感觉我看了太久,要么有一个简单的方法,要么有一个更好的解决方案,我看不到了。对于上下文,我正在构建一个用于处理React包中可翻译内容字符串的包。所以可以这样使用。

// IdsWithParameters in above example
interface ContentStringsWithAcceptableParameters {
  "errors.404.title": {},
  "errors.404.content": {
     pageUrl: string;
  },
  "errors.retryAttemptsLeft": {
    attemptsLeft: number;
  }
}

interface Props<I extends ContentStringsWithAcceptableParameters> {
  id: keyof I;
  params: I[keyof I];
}

// The react component we'll be using
function Text(props: Props<ContentStringsWithAcceptableParameters>) {
  const text = intlFunctionThatGetsTheTranslatedText(props.id, props.params);

  return <>{text}</>
}
javascript reactjs typescript lookup
1个回答
1
投票

我想如果我们简化一下这个例子,我们就能理解我们要做的事情。

interface ITest {
  n: number;
  b: boolean;
}

const f = <K extends keyof ITest>(
  x: {
    id: K,
    params: ITest[K],
  },
) => true;

f({ id: 'n', params: 1 });    // no type error
f({ id: 'n', params: true }); // Type 'true' is not assignable to type 'number'

f({ id: 'b', params: true }); // no type error
f({ id: 'b', params: 1 });    // Type 'number' is not assignable to type 'boolean'

我们可以指定一些通用(K 在上面的例子中)扩展了一个类型的键。然后我们就可以使用这个键来获取我们要找的类型。

© www.soinside.com 2019 - 2024. All rights reserved.