gpt4 book ai didi

TypeScript 根据输入类型定义通用输出类型

转载 作者:行者123 更新时间:2023-12-04 00:49:38 24 4
gpt4 key购买 nike

对于我的 React-Native 项目,我试图获得尽可能多的自动完成和类型验证。挑战之一是为我使用的样式表库配置类型。

扩展样式表如下所示:

const styles = createStyles({
variable1: 100,
variable2: "10rem",

header: {
width: "100%",
height: 40,
alignContent: "center",
flex: "$flexAll",
margin: "$gapMD"
}
})

当我定义样式时,每个样式值不仅应该接受其原始类型,还应该接受stringfunction

当库处理完样式表后,结果是一个常规的 React-Native 样式表。因此函数的结果应包含与函数输入相同的属性,但属性应映射到原始样式类型。

例如flex应该是一个number,而不是一个number |字符串 |功能 |等等

这是我到目前为止所得到的:

import { ImageStyle, TextStyle, ViewStyle } from "react-native"
import EStyleSheet from "react-native-extended-stylesheet"

type Function<K> = () => K

type AllStyles = ImageStyle & TextStyle & ViewStyle
type StyleSet<T> = { [P in keyof T]: AllStyles }

type EValue<T> = T | string & {}
type EVariable<K> = EValue<K> | Function<EValue<K>>
type EStyle<T> = { [P in keyof T]: EVariable<T[P]> }

type EAnyStyle = EStyle<ImageStyle> | EStyle<TextStyle> | EStyle<ViewStyle>
type EStyleSet<T> = { [P in keyof T]: number | string | EAnyStyle | EStyleSet<T> }

export const createStyles = <T>(styles: EStyleSet<T>) =>
EStyleSheet.create(styles) as StyleSet<T>

不幸的是,自动完成不能完全工作,我觉得我的定义变得有点太复杂了。结果类型也不完全正确。

我真的希望有一个 TypeScript 向导可以帮助我完成这项工作。

我已经设置了一个可用于测试某些类型的沙箱:
https://codesandbox.io/s/typescript-style-mania-h62cv

最佳答案

如果方向正确,请告诉我:

import {FlexStyle, ImageStyle, TextStyle, ViewStyle} from './react-native';

///////////////////////////////////////////////////////
// MOCK

const EStyleSheet = { create: obj => obj };

///////////////////////////////////////////////////////
// TYPES

// thanks ts-essentials.
type Primitive = string | number | boolean | bigint | symbol | undefined | null;
type Builtin = Primitive | Function | Date | Error | RegExp;
type ExtendTypes<T, E> = T extends Builtin
? T | E
: T extends Map<infer K, infer V>
? Map<ExtendTypes<K, E>, ExtendTypes<V, E>>
: T extends ReadonlyMap<infer K, infer V>
? ReadonlyMap<K, ExtendTypes<V, E>>
: T extends WeakMap<infer K, infer V>
? WeakMap<K, ExtendTypes<V, E>>
: T extends Set<infer U>
? Set<ExtendTypes<U, E>>
: T extends ReadonlySet<infer U>
? ReadonlySet<ExtendTypes<U, E>>
: T extends WeakSet<infer U>
? WeakSet<ExtendTypes<U, E>>
: T extends Array<infer U>
? Array<ExtendTypes<U, E>>
: T extends Promise<infer U>
? Promise<ExtendTypes<U, E>>
: T extends {}
? { [K in keyof T]: ExtendTypes<T[K], E> }
: T;


type AllStyles = ImageStyle & TextStyle & ViewStyle;
type StyleSet<T> = Pick<{
header: ViewStyle;
font: TextStyle;
}, Extract<'header' | 'font', keyof T>>;

const createStyles = <T extends {
// I would add precise definition for the properties here too.
// header?: ExtendTypes<ViewStyle, Function | String>;
// font?: ExtendTypes<TextStyle, Function | String>;
[key: string]: string | number | Function | ExtendTypes<AllStyles, Function | String>; // Capital to keep string unions.
}>(styles: T): StyleSet<T> =>
EStyleSheet.create(styles);

///////////////////////////////////////////////////////
// TEST

const styles = createStyles({
variable1: 100,
variable2: "10rem",

header: {
width: "100%",
height: 40,
alignItems: "flex-start",
alignSelf: "$alignSelf", // autocomplete, but also allow custom values
flex: "$flexAll",
margin: "$gapMD",
// autocomplete should work here, but doesn't
// now it works
},
font: {
fontSize: 20
}
});

const imageStyle: ImageStyle = {
alignItems: "center"
};

// Valid
console.log("header", styles.header);
console.log("header.fontSize", styles.font.fontSize);
console.log("imageStyle.alignItems", imageStyle.alignItems);

// Invalid: ViewStyle doesn't have textTransform
// now it works
console.log("header.textTransform", styles.header.textTransform);

// Invalid: TextStyle doesn't have resizeMode
// now it works
console.log("font.resizeMode", styles.font.resizeMode);

关于TypeScript 根据输入类型定义通用输出类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60783230/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com