Skip to content

Instantly share code, notes, and snippets.

@yao3060
Last active July 11, 2024 01:41
Show Gist options
  • Select an option

  • Save yao3060/e0405b5662a53aaf655a48fbc824f4ea to your computer and use it in GitHub Desktop.

Select an option

Save yao3060/e0405b5662a53aaf655a48fbc824f4ea to your computer and use it in GitHub Desktop.
const ENMessages = {
"welcome": "Welcome",
"default": {
"login": "Login",
"email_login": "Email login",
"social_login": "Social login",
"web3_login": "Web3.0 login",
"logout": "Logout",
"account": "Account",
"create_account": "Create an account",
"search_your_want": "Search your want",
"test": {
"aa": "AA"
}
},
"products": {
"label": "dddd"
}
}
type NestedKeyOf<ObjectType extends object> =
{ [Key in keyof ObjectType & (string | number)]: ObjectType[Key] extends object
? `${Key}` | `${Key}.${NestedKeyOf<ObjectType[Key]>}`
: `${Key}`
}[keyof ObjectType & (string | number)];
type ENMessageKeys = NestedKeyOf<typeof ENMessages> | '';
function getDeepValue(path: ENMessageKeys) {
if (path === '') {
return 'NULL'
}
return path.split('.').reduce((acc: any, current: string) => {
return (acc && acc[current]) ? acc[current] : path
}, ENMessages)
}
import get from 'lodash.get';
const language = {
"test test": "test test",
"search": "搜索",
"home": {
"home": "首页",
"hot_brands": "热门品牌",
"new_products": "最新商品",
"discount": "限时折扣"
},
"products": {
"Product": "Product"
}
}
const isString = <T = any>(str: string | T): str is string => typeof str === "string";
/**
* Common utils
*/
type Primitives = string | number | symbol;
/**
* If first argument is empty string, avoid using dot (.)
* If first argument is non empty string concat two arguments andput dot (.)
* between them
*/
type Concat<Fst, Scd> =
Fst extends string
? Scd extends string
? Fst extends ''
? `${Scd}`
: `${Fst}.${Scd}`
: never
: never
{
// type Test = Concat<'hello', 'bye'> // "hello.bye"
}
/**
* Obtain union of all possible paths
*/
type KeysUnion<T, Cache extends string = ''> =
T extends Primitives ? Cache : {
[P in keyof T]:
| Concat<Cache, P>
| KeysUnion<T[P], Concat<Cache, P>>
}[keyof T]
{
// // "user" | "user.description" | "user.description.name" | "user.description.surname"
// type Test = KeysUnion<typeof language> // eslint-disable-line
}
/**
* @see https://stackoverflow.com/questions/68387436/is-it-possible-to-create-object-key-path-string-autocomplete-for-an-object-purel
* @example t('home.hot_brands')
*/
export default function t(keys: KeysUnion<typeof language, "">) {
const value = get(language, keys)
return isString(value) ? value : keys
}
@yao3060
Copy link
Author

yao3060 commented Jul 11, 2024

const ENMessages = {
  "welcome": "Welcome",
  "default": {
    "login": "Login",
    "email_login": "Email login",
    "social_login": "Social login",
    "web3_login": "Web3.0 login",
    "logout": "Logout",
    "account": "Account",
    "create_account": "Create an account",
    "search_your_want": "Search your want",
    "test": {
      "aa": "AA"
    }
  },
  "products": {
    "label": "dddd"
  }
}

type NestedKeyOf<T> =
  { [K in keyof T & (string)]: T[K] extends object ? K | `${K}.${NestedKeyOf<T[K]>}`: K}[keyof T & (string)];

type ENMessageKeys = NestedKeyOf<typeof ENMessages>;

function getDeepValue(path: ENMessageKeys) {
  //
}

getDeepValue('default.test.aa') // valid
getDeepValue('default.test.a')  // invalid

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment