更新:感谢@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接口),指定允许的键和允许与每个特定键一起使用的类型参数。在不同的地方,他们会希望指定一个对象,该对象具有和。id
和 params
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}</>
}
我想如果我们简化一下这个例子,我们就能理解我们要做的事情。
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
在上面的例子中)扩展了一个类型的键。然后我们就可以使用这个键来获取我们要找的类型。