在 TypeScript 中,某些类型是使用extends keyof
或定义的in keyof
。我试图理解它们的意思,但到目前为止我没有成功。
我得到的是,keyof
单独返回一个联合类型,该类型将所有名称作为可能的值存在于您在keyof
.
type T = keyof string;
Run Code Online (Sandbox Code Playgroud)
T
因此等价于startsWith | endsWith | trim | substring | ...
。
这样对吗?
现在,如果我去想想什么extends keyof
和in keyof
意味着,我的直觉以下称:
extends keyof
是派生自 的任何类型T
,即它具有所有这些可能的值,但可能更多。in keyof
是从 中获取值的任何类型T
,但不一定是全部(有可能,但可能更少)。所以,从这个 POVextends keyof
将描述一个>=
关系,in keyof
将描述一个<=
关系。这样对吗?如果不是,那什么是正确的?
我想声明一个类型强制的项目数组,并能够从中派生出联合类型。如果您没有明确地为数组中的项目指定类型,则此模式有效。我不知道如何最好地解释它,所以这里是一个例子:
例 1
type Pair = {
key: string;
value: number;
};
const pairs: ReadonlyArray<Pair> = [
{ key: 'foo', value: 1 },
{ key: 'bar', value: 2 },
] as const;
type Keys = typeof pairs[number]['key']
Run Code Online (Sandbox Code Playgroud)
例2
type Data = {
name: string;
age: number;
};
const DataRecord: Record<string, Data> = {
foo: { name: 'Mark', age: 35 },
bar: { name: 'Jeff', age: 56 },
} as const;
type Keys = keyof typeof DataRecord;
Run Code Online (Sandbox Code Playgroud)
以下是使用as const
. …
我想声明一种类型,它需要将给定类型的所有键都T
包含在一个数组中,例如:
checkKeys<T>(arr: Array<keyof T>): void {
// do something
}
interface MyType {
id: string;
value: number;
}
Run Code Online (Sandbox Code Playgroud)
目前,如果调用checkKeys<MyType>
TS 将认为传递的值是有效的,如果它包含MyType
( id | value
) 的任何键:
checkKeys<MyType>(['id', 'value']); // valid
checkKeys<MyType>(['id']); // valid
checkKeys<MyType>(['id', 'values']); // invalid
Run Code Online (Sandbox Code Playgroud)
是否可以要求在数组中指定所有键?
假设我们有如下所示的TypeScript代码:
type User = {
id: number,
name: string,
}
let user1: User = {id: 123, name: "Hello"};
let user2: User = {id: 456, name: "World"};
let keys: (keyof User)[] = ["id", "name"];
for (let key of keys) {
user1[key] = user2[key];
}
Run Code Online (Sandbox Code Playgroud)
这给出了错误
Type 'string | number' is not assignable to type 'never'.
Run Code Online (Sandbox Code Playgroud)
为声明
Type 'string | number' is not assignable to type 'never'.
Run Code Online (Sandbox Code Playgroud)
如果我们将的定义更改keys
为
user1[key] = user2[key];
Run Code Online (Sandbox Code Playgroud)
错误消失了,但是我们失去了类型安全性。
有什么方法可以在保持类型安全的同时避免发生此错误?
所以来自:
export interface Category{
val: string;
icon: string
}
const categoryArray: Category[] = [
{
val: 'business',
icon: 'store'
},
{
val: 'media',
icon: 'video'
},
{
val: 'people',
icon: 'account'
},
...
Run Code Online (Sandbox Code Playgroud)
我想像这样找回 Union 类型:
'business' | 'media' | 'people' ...
Run Code Online (Sandbox Code Playgroud)
我不知道有什么样的语法或帮助程序,也许根本没有。我意识到这种方式可能是倒退的,也许应该使用枚举,但在此之前,我想知道这是可能的。
我想做的一些虚构的例子,但我希望解决方案更加复杂
type Cats = keysof[] categoryArray 'val'
type Cats = valuesof categoryArray 'val'
Run Code Online (Sandbox Code Playgroud)
以下内容很接近,但返回string
:
export type CatsValType = typeof categories[number]['val']
Run Code Online (Sandbox Code Playgroud)
或以下;我需要字符串文字而不是类型
type ValueOf<T> = T[keyof T];
type KeyTypes = ValueOf<typeof categories[number]> // Returns: `string`
Run Code Online (Sandbox Code Playgroud)
还有类似的问题,例如: …
有没有办法进行以下类型检查?
function getNumberFromObject<T>(obj: T, key: keyof T): number {
return obj[key] // ERROR: obj[key] might not be a number
}
Run Code Online (Sandbox Code Playgroud)
我想指定它key
不仅应该是 的键T
,而且应该是带有number
值的键。
我尝试编写一个泛型函数,汇总数据库更新的更新数据.
传递参数:
即使我使用限制键的类型keyof R
,我也不能将具有该键的新对象分配给Partial<R>
常量.我收到错误我该Type '{ [x: string]: any[]; }' is not assignable to type 'Partial<R>'.
怎么做才能使下面的代码工作?如果我用R
非泛型类型替换泛型类型,它可以工作.但这不是我需要的.
interface BaseRecord {
readonly a: ReadonlyArray<string>
}
function getUpdateData<R extends BaseRecord>(record: R, key: keyof R, newItem: string) {
const updateData: Partial<R> = { [key]: [...record[key], newItem] }
return updateData
}
interface DerivedRecord extends BaseRecord {
readonly b: ReadonlyArray<string>
readonly c: ReadonlyArray<string>
}
const record: DerivedRecord = { a: [], b: [], c: …
Run Code Online (Sandbox Code Playgroud) 我想定义一个数组类型,它必须包含给定类型的嵌套属性名称链。
假设我有一个类型:
type Foo = {
outer: {
inner: any;
}
}
Run Code Online (Sandbox Code Playgroud)
现在我想定义一个包含 2 个元素的 Array 类型:
type PropertyList<T, K1 extends keyof T, K2 extends keyof T[K1]> = [K1, K2];
Run Code Online (Sandbox Code Playgroud)
我想像这样使用它:
let myList:PropertyList<Foo> = ["outer", "inner"]
Run Code Online (Sandbox Code Playgroud)
所以我希望编译器检查包含的 2 个属性名称是否是 Foo 的嵌套属性名称。
但是我不能只用 1 个泛型参数定义 PropertyList,然后我收到这个错误:
TS2314: Generic type 'PropertyList' requires 3 type argument(s)
Run Code Online (Sandbox Code Playgroud)
知道如何推断嵌套的 keyof 类型而不必指定它们吗?
我需要使用类属性名称的一些子集作为映射中的值以在类内部使用。在下面的示例中,我用数组替换了地图。问题是,如果属性被标记,private
它不会在keyof
列表中列出。如果我需要包含私有名称,如何指定密钥类型?
var keys: Array<keyof A> = ["x", "y"]; // Error
class A {
private x = 7;
public y = 8;
private keys: Array<keyof A> = ["x", "y"]; // Error
}
Run Code Online (Sandbox Code Playgroud)
对于类外部的变量和类内部的私有属性都存在相同的错误:
类型“x”不可分配给类型“y”。
我想知道如何正确推断我的函数的第二个和第三个模板
假设一个简单的界面
interface ISome {
a: string;
b?: {
c: string;
};
}
Run Code Online (Sandbox Code Playgroud)
关注作品
function pathBuilder<
K1 extends keyof ISome,
K2 extends keyof NonNullable<ISome[K1]>>(p: K1, p2?: K2) {
let res = String(p);
if (p2) { res += "." + p2; }
return res;
}
const pathTest = pathBuilder("b", "c"); // ---> "b.c" and intellisense works on parameters
Run Code Online (Sandbox Code Playgroud)
但我需要通过指定另一种类型来概括该函数以使其工作(我不想传递对象实例来指定类型)
所以,以下不起作用
function pathBuilder<
T,
K1 extends keyof T,
K2 extends keyof NonNullable<T[K1]>>(p: K1, p2?: K2) {
let res = String(p); …
Run Code Online (Sandbox Code Playgroud) keyof ×10
typescript ×10
generics ×3
typeof ×2
constants ×1
extends ×1
javascript ×1
private ×1
union-types ×1